48 KiB
Implement the optional integration modules and captured registration API
Status: implementation in progress. Stages 1 and 2 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.workcomposing these three modules during development. Preserve unrelated local workspace content; do not commitgo.work/go.work.sumor 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.
- Create the two nested module directories and their
go.modfiles 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. - Move configuration-owned material from
config.go,selectors.go,validate.go,show.go,sources.go, andexplain.gointo ckconfig. Treat these as source to refactor into the selected API, not exports to retain. - Move
promptkit.goandpromptkit_scope.gointo ckprompt. Its scope adapter may import ckconfig, never the reverse. Remove the root integration surface. - Relocate configuration and PromptKit tests/fixtures with their owning module.
Split mixed
cancellation_test.goandperformance_reports_test.goresponsibilities. Core dispatch/binding/registry/outcome and Cobra tests stay in the root. Retain useful benchmarks without requiring numerical targets. - Move the old
examples/simpleto ckconfig'sexamples/simpleand the oldexamples/composedto ckprompt'sexamples/composed, including READMEs. Create the genuine core consumer in Stage 13. No optional-library consumer remains inside the root module. - 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.
- Replace ConfigKit severity in
Diagnosticwith the selected coreSeverityand warning/error constants. ProvideAcquired[T]and retain the selectedIdentity,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. - Implement the infallible
NewCommand[I],Group,RootGroup,WithError, andNoCommandsignatures from the API document. Use an opaque handle to a private captured record containing metadata, children, typed payload, retained issues, placement, and absence. - Capture
CommandSpec.Childrenand binding/argument metadata slices. Copy caller-owned collections at capture, sharing already immutable child records. Do not recursively clone every subtree at each ancestor. - 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.
WithErrorretains 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.- 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.
- Refactor
binding.goaround the finalizedValueFlag,BoolFlag,RepeatFlag,ValueArgument, andRepeatArgumentsignatures. Capture defaults/metadata and retain nil parser/setter or cardinality defects as construction issues rather than returning factory errors. - 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.
- 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.
- 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.
- 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.
- 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: existing presence/repetition/help tests, adjusted to the selected constructors, plus focused converter call counts and repeated-slice independence. Do not add a new grammar restriction.
Stage 4: Implement captured flag application
Outcome: integrations compose typed inputs without parser/setter access.
- Implement opaque
FlagValues[I],CaptureFlags[Outer, I], andFlagValues.ApplyToexactly as selected. Capture original handles and target accessors eagerly; retain invalid inner bindings/nil accessors for installation. - 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.
- Apply only selected original bindings to
*I. Copied handles work; lookalikes, uncaptured selections, or nil destinations matchErrFlagWiring. A zero store with no selected bindings is valid for a valid destination. - Defer captured inner required checks to the selected subset at
ApplyTo. Preserve required help metadata. Missing required supplied values matchErrFlagInput. Core-owned repeated collections are fresh per application. - Add the two public sentinel categories and common wrapped-error classification:
wiring failures from
CheckInputare operational; missing input and ordinary input-validation failures are usage. These paths stop before state/acquisition. - 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: original/copied/lookalike identity, defaults and presence, selected required flags, wrapped errors, nil destination, empty selection, repeatable independence, and no second conversion. Check both ordinary and captured bindings through the same preparation path.
Stage 5: Compile typed runners and real built-in declarations
Outcome: built-ins and ordinary commands share capture and typed execution.
- Replace the prototype factory/check/run
anypayload handoffs with a private compiled runner retainingIinside one typed invocation closure. Conversion precedes materialization; then initialize once, apply values, callCheckInput, and run the selected handler. - Omitted
NewInputyields the exact zero value. Do not allocate arbitrary pointers, repair aliases, catch arbitrary caller panics, or clone closure state. - Provide a narrow private execution context containing invocation streams,
cancellation, and current core presentation access. Public callbacks receive
only the selected
InvocationandI. - 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.
- Retain help targets, bare/group help, runnable-parent behavior, and version
semantics from the CLI reference. Default version is application identity;
--scope commandkituses embedded module build information. Text/YAML choices and development/replacement identity behavior stay selected. - 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.
- Implement one private batch installer used by both public operations.
Newvalidates identity, creates an unpublished empty app, constructs its real built-ins, and submits built-ins plus caller declarations in one batch. - 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.
- Check sibling/root collisions, occupied roots, and pending-batch roots.
RootGroupis rejected below root independent of its name. Real help/version nodes supply their reservation; installed real integration roots supply theirs. - Stage only additions in a pending map and commit after the entire batch succeeds.
A failed
Newexposes no app; a failedRegisterleaves registry and derived metadata intact. Separate successful calls are not one transaction. - 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.
- 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.
- Move existing neutral command/help/binding/parse DTOs from
internal/cobratointernal/commandmeta. Add private snapshot-local command keys as needed. Public facade types remain owned declarations, not aliases to these DTOs. - 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.
- 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.
- Return the selected neutral key, path, and raw occurrences from the adapter.
Execute against the runner table belonging to that session; remove the second
commandAtpath resolution. Keys are private and meaningful only within their snapshot. - 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. - 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.
- 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.
- Implement
Selection,Operation(Validate/Show/Sources/Explain),Request,Viewand its three facets,Scope[I, S],Selector[I], andSuite[I, S]from the finalized API. Keep ConfigKit-shaped records/paths here, with no neutral copies in the core. - Implement
WithScopeErroras 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 byCommand, not by this error-attachment operation; it introduces no new declaration lifecycle. - 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. - 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.
- 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.
- Implement
ckconfig.Command[I, S]as a capturedRootGroup("config", ...). Capture scope records, operation/applicability lists, callbacks, ordered discovery metadata, scope lookup, and original applicable selector handles. - 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.
- Generate each inspection verb if at least one scope supplies it.
config scopeslists actual capabilities in app/promptkit/other alphabetical order without input/state/provider calls. It supports the selected text/YAML reports. - 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 withCaptureFlagsand ordinary standard bindings. - 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.
- In shared
CheckInputpreparation, 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. - For each selected scope, initialize
Iindependently (factory or zero), apply only its original applicable handles, and callCheckInput(scopeName, selection, input). Retain successful records on the same outer pointer. Stop after failure; later inputs need not be initialized. - 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. - Preserve supplied but inapplicable conversion and selected required checks. Missing/unknown scope/format/path failures are usage; wrapped wiring is operational.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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. - 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.
- Implement
PromptRequest,ProfileRequest, andSuite[I, S]with the exact selected types. Definition selectors are ordinary core flags; selection is ckconfig's type. - 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. - 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. - 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. - 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.
- 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.
- Implement
ckprompt.Command[I, S]with a root-only promptkit tree containingshow promptand/orshow profilefor supplied callbacks. Do not add list/catalog commands. - If both callbacks are absent, return plain
NoCommand()with any retained adapter issues attached viaWithError. Ignore unused selector bindings; no command, help entry, or namespace remains. If a capability exists, capture needed selectors and let core validate generated bindings. - Use a private definition-input preparation helper with
CaptureFlags. Convert once, initialize suite input once, apply its selected complete flag set, and run scope-freeCheckInput(selection, input). Initialize shared state once only after preflight/input checks succeed, then call the selected inspection callback once. - Preserve required ID operand,
--config,--overlay, prompt-only--version, and text/YAML--formatdefaulting 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. - 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
{}. - 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.
- 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.
- Implement
examples/coreusing typed core declarations, an ordinary domain group/runnable command, presence and repeated values, help, and version. It imports neither optional library nor optional integration. - Rewrite ckconfig's simple example using
AppCommand, with no dummy input/state types at its consumer call site. Retain a useful typed application command. - 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. - 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.
- 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.
- Place public cross-integration composition tests in ckprompt. Root tests/tools must not import nested integrations to obtain broader coverage.
- 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.
-
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.
-
Keep root
releasekit.jsonand add a profile in each integration directory. Use this exact selection table:Launcher selector Product module_dirProfile coreCommandKit.releasekit.jsonckconfigCommandKit ckconfigintegrations/ckconfigintegrations/ckconfig/releasekit.jsonckpromptCommandKit ckpromptintegrations/ckpromptintegrations/ckprompt/releasekit.json -
Each profile sets
remote: origin,expected_push_url: https://gitea.maximumdirect.net/eric/CommandKit.git, andvalidation.shared_filesexplicitly to rootCOPYRIGHT,LICENSE, anddocs/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 inchecks. -
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. -
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, andGOTOOLCHAIN=local, retaining ignored.releasekit/binstorage. Apply workspace-off/local-toolchain settings to delegated publication too. -
Delegate with options preceding VERSION:
releasekit publish --repo ROOT --config PROFILE --expected-module MODULE_DIR VERSIONThe 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.
-
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.
-
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.
-
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.
-
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.
-
Give each integration a module-local README and actual
COPYRIGHT/LICENSEplus applicabledocs/oss/attribution.mdand 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. -
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.
-
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.
-
Prepare new notes:
Note Product/title version Full tag for immutable links docs/releases/v0.2.0.mdCommandKit v0.2.0 v0.2.0integrations/ckconfig/docs/releases/v0.1.0.mdCommandKit ckconfig v0.1.0 integrations/ckconfig/v0.1.0integrations/ckprompt/docs/releases/v0.1.0.mdCommandKit ckprompt v0.1.0 integrations/ckprompt/v0.1.0Explain 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.
-
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.
-
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.
-
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.
-
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.
-
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. -
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.modand availablego.sumto temporary paired mod/sum files (for example,core.modandcore.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 rungo 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 ./...andgo list -modfile=TEMP_MOD -mod=readonly -m allseparately 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.
- Copy each module's final
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.