Reconcile module docs and release materials

This commit is contained in:
2026-10-11 02:06:06 +00:00
parent 18e81a5579
commit d2b5b0f3a8
45 changed files with 2380 additions and 362 deletions

View File

@@ -85,9 +85,12 @@ constructing application command inputs.
## Configuration scopes
An application installs one configuration suite with `RegisterConfig`. Its
An application installs the declaration returned by
`ckconfig.Command(ckconfig.Suite[Input, State]{...})` through
`commandkit.New` or `App.Register`. For the common single application scope,
`ckconfig.AppCommand` returns a convenience declaration. The installed
`config scopes` command lists scope names and the configuration operations
currently installed for those scopes:
currently available for those scopes:
```text
example config scopes
@@ -102,10 +105,9 @@ runtime context or acquire configuration. It reports the intersection between
declared scope capabilities and installed handlers, so an operation is listed
only when the corresponding command is available.
Applications can register the `promptkit` scope with `NewPromptKitScope` to
expose PromptKit engine configuration through these handlers. This configuration
scope can be installed without registering PromptKit prompt or profile
definition commands.
Applications can add `ckprompt.ConfigScope(loadEngine)` to the ConfigKit suite
to expose PromptKit engine configuration through these handlers. This scope
does not install PromptKit prompt or profile definition commands.
### Validate configuration
@@ -231,12 +233,12 @@ serialized as `[]`.
## PromptKit definition inspection
Applications can install prompt and profile inspection independently with
`RegisterPromptKit`. When acquisition is reached, the handler invokes its
registered inspection callback once with the caller's selection and context.
The bundled `NewPromptKitSuite` helper acquires an engine through the application
loader and asks PromptKit to inspect its captured named definition. The loader
can construct or reuse an engine; direct suite callbacks retain their own
implementation and lifecycle.
`ckprompt.Command(suite)`, passing the resulting declaration to core. The
`ckprompt.FromEngine(loadEngine)` adapter supplies callbacks that acquire an
engine only after input checks pass and inspection is reached. The loader
receives invocation context, selection, input, and state; its implementation
controls whether an engine is constructed or reused. Direct suite callbacks
retain their own implementation and lifecycle.
CommandKit's inspection path does not execute prompts, contact model providers,
or resolve provider credential values. Application acquisition and direct

View File

@@ -1,88 +1,156 @@
# Consumer guide
CommandKit's currently implemented Go API is the root `commandkit` package.
Start with an `App`, register CommandKit's standard inspection families, register application
commands, and call `App.Execute` with the caller's context and streams. The
caller retains process startup, signal handling, and exit mapping.
CommandKit is distributed as three Go modules. Start with the core and add an
integration module only when the application uses that library. Each module
returns core `commandkit.Command` declarations, which the application installs
through `commandkit.New` or `App.Register`.
## Module selection
| Import | Use when |
| --- | --- |
| `gitea.maximumdirect.net/eric/CommandKit` | The application needs typed command declarations and common CLI behavior. |
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | The application wants ConfigKit-backed configuration scopes and reports. |
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | The application wants PromptKit engine configuration or named prompt/profile inspection. |
The two integrations are independent optional imports. `ckprompt` uses the
public scope and error contracts from `ckconfig`; importing it does not add the
`config` family. An application that wants both families passes both returned
declarations to core. The [maintained examples](../../README.md#examples) show
core-only, ConfigKit-only, and composed applications.
## Go compatibility
The consumer minimum is declared in [go.mod](../../go.mod): Go 1.26.0.
ReleaseKit v0.3.0 requires that version and is selected as a tool dependency in
the same module graph. The minimum therefore applies to library consumers even
though production packages do not import ReleaseKit. Consumers using Go 1.25
need a Go 1.26 or newer toolchain to adopt this revision.
All three modules declare a consumer minimum of Go 1.26.0. The root module also
selects ReleaseKit v0.4.0 as a Go tool, which makes that tool's module graph part
of the root consumer module requirements even though production packages do not
import ReleaseKit. The [release policy](../policy/release.md#consumer-minimum-and-release-toolchain)
defines the support assumption. Maintainers use Go 1.26.8 for validation and
publication; see the [release procedure](../release.md#release-toolchain).
The [release policy](../policy/release.md#consumer-minimum-and-release-toolchain)
defines support assumptions and versioning for changes to that minimum.
Maintainers select their validation toolchain separately in the
[release procedure](../release.md#release-toolchain). Updating that toolchain's
patch version alone leaves the consumer minimum unchanged.
## Core commands
## A configuration scope
Use [`NewConfigKitScope`](../../config.go) to adapt one ConfigKit loader. The
loader receives the invocation's explicit `Selection`; the application decides
how those supplied config and overlay values map to its inputs.
Declare typed flags and operands with `CommandSpec[I]`, then capture them with
`NewCommand`. Bindings deliver `Supplied[T]`, which distinguishes an omitted
default from an explicitly supplied empty, false, or zero value.
```go
scope, err := commandkit.NewConfigKitScope[appContext, appConfig](
"app",
"Application settings.",
func(ctx context.Context, selection commandkit.Selection, app appContext) (*configkit.Result[appConfig], error) {
return loadAppConfig(ctx, selection, app)
},
package example
import (
"fmt"
"strconv"
commandkit "gitea.maximumdirect.net/eric/CommandKit"
)
if err != nil {
return err
type GreetInput struct {
Count commandkit.Supplied[int]
}
func Greeting() commandkit.Command {
countDefault := 1
return commandkit.NewCommand(commandkit.CommandSpec[GreetInput]{
Name: "greet", Summary: "Write a greeting.",
Flags: []commandkit.Flag[GreetInput]{
commandkit.ValueFlag(
commandkit.FlagMeta{Name: "count", Usage: "Number of greetings."},
&countDefault, strconv.Atoi,
func(input *GreetInput, value commandkit.Supplied[int]) {
input.Count = value
},
),
},
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
_, _ = fmt.Fprintln(invocation.Streams.Out, input.Count.Value)
return commandkit.Success()
},
})
}
err = commandkit.RegisterConfig(app, commandkit.ConfigSuite[appContext]{
Scopes: []commandkit.ConfigScope[appContext]{scope},
})
```
`config show`, `config sources`, and `config explain` use the configuration
captured by that load. A scope can support only the operations it provides.
When several scopes share invocation-local application state, create it in
`ConfigSuite.NewContext`; use typed `Selector` bindings to copy only the values
that apply to each scope. See the [composed example](../../examples/composed/README.md)
for a cache shared by the `app` and `promptkit` scopes.
The application supplies `context.Context`, argv without the executable name,
and output streams to `App.Execute`; it decides how the returned status maps to
process exit. `New` installs generated help/version and caller declarations as
one batch. `Register` validates each call as a batch before changing that App.
Invalid declaration errors retain their wrapped identity for `errors.Is` and
`errors.As`.
Declarations copy their metadata and slice inputs when captured, retain callback
references, and can be reused across applications. Copies of a typed binding
preserve its identity; a separately constructed lookalike does not. Supplied
values convert before input construction. A command's `NewInput` creates input
only when execution reaches it; help does not construct caller input or run
provider callbacks.
## ConfigKit scopes
For an application with one ordinary app configuration loader,
`ckconfig.AppCommand` supplies the state-free convenience declaration:
```go
app, err := commandkit.New(
commandkit.Identity{Name: "Example", Version: "dev"},
ckconfig.AppCommand(loadAppConfig),
)
```
`loadAppConfig` has the signature
`func(context.Context, ckconfig.Selection) (*configkit.Result[T], error)`.
Construction, installation, and help do not call it. `Selection` preserves
whether config and overlay paths were explicitly supplied, including empty
values.
Use `ckconfig.Command(ckconfig.Suite[I, S]{...})` when the application needs
multiple named scopes, selector flags, scope-aware input checks, or shared
acquisition state. Each selected scope receives its own initialized input. The
suite's `NewState` runs once for the inspection invocation after selected input
checks pass, and the resulting state is shared by selected acquisitions. The
application owns the state type and what it caches. `ckconfig.FromConfigKit`
adapts a typed ConfigKit loader without calling it during construction.
The `config` family provides scope discovery, validation, native effective YAML,
source inventory, and path explanation for the capabilities declared by its
scopes. The [CLI reference](../cli.md#configuration-scopes) owns operator
syntax and report details.
## PromptKit configuration and definitions
Register `NewPromptKitScope` with the config suite when you want the effective
PromptKit configuration and its ConfigKit provenance available under `config`.
Register `NewPromptKitSuite` and `RegisterPromptKit` separately to enable
`promptkit show prompt` and/or `promptkit show profile`. Each adapter calls the
owning public inspection method and preserves acquisition diagnostics with a
failed named lookup. Definition inspection does not invoke execution APIs or
resolve provider credentials.
`ckprompt.ConfigScope(loadEngine)` returns a `ckconfig.Scope` for the PromptKit
engine's captured configuration. Add that scope to a `ckconfig.Suite` to expose
it under `config`; it does not install named definition commands.
The [composed example](../../examples/composed/README.md) shares its ordinary app and
engine-loading functions across the configuration and definition suites. It
also keeps `session restore` as an application-owned typed command, including
its session data and domain outcome mapping.
`ckprompt.FromEngine(loadEngine)` supplies PromptKit named prompt and profile
inspection callbacks. Set its `NewInput`, `NewState`, selectors, or validation
when the application needs them, then pass `ckprompt.Command(suite)` to core.
Prompt and profile capabilities can be installed independently by providing
only the corresponding callback. Each selected inspection gets a fresh input
and one shared state value for that invocation. The loader receives the
invocation context, explicitly supplied selection, input, and state. The adapter
uses PromptKit's public inspection methods and preserves acquisition diagnostics
and error identity.
## Typed application commands
Definition inspection does not execute a prompt, contact a model provider, or
resolve credential values. Credential fields in reports identify environment
variable names and requirements only; they do not report credential
availability.
Declare flags, operands, and a typed input struct with `NewCommand`. Bindings
preserve whether a value was explicitly supplied, so an explicit zero can differ
from an omitted default. `RepeatFlag` retains occurrence order. The
[simple example](../../examples/simple/README.md) combines both features with a typed
ConfigKit scope.
The [composed example](../../integrations/ckprompt/examples/composed/README.md)
combines app and PromptKit config scopes, independently registers profile
inspection, and adds an application-owned `session restore` command.
## Outcomes and process exit
## Outcomes and ownership
Handlers return `Success`, `Failure`, or an application-owned `Outcome`. The
caller chooses how a nonzero status maps to process exit; `Execute` never exits
the process. It writes CommandKit diagnostics to the supplied error stream and
returns the resulting classification and delivery information. Applications
keep their domain meanings and output in their own handlers.
Core classifies usage and operational failures while preserving application
domain outcomes and supported error identity. Report and diagnostic delivery
errors remain inspectable separately from the operation cause. The caller owns
process startup, signal handling, and exit mapping; `Execute` never exits the
process.
Exact CommandKit contracts are documented on the exported declarations and
their GoDoc comments. ConfigKit owns configuration decoding and provenance;
consult its [inspection API](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/dc09959cca4e105f49ec316c6d4ba585bd2340bd/inspection.go).
PromptKit owns prompt formats and profile resolution; consult its [public
engine methods](https://gitea.maximumdirect.net/eric/promptkit/src/commit/4b8169da286917fde7875425bb32b799b12c6af3/engine.go),
Go declarations and GoDoc own exact exported contracts. ConfigKit owns
configuration decoding, validation, and provenance. PromptKit owns prompt
formats, profile resolution, and inspection details. See the
[ConfigKit inspection API](https://gitea.maximumdirect.net/eric/ConfigKit/src/commit/dc09959cca4e105f49ec316c6d4ba585bd2340bd/inspection.go),
[PromptKit engine methods](https://gitea.maximumdirect.net/eric/promptkit/src/commit/4b8169da286917fde7875425bb32b799b12c6af3/engine.go),
[configuration inspection](https://gitea.maximumdirect.net/eric/promptkit/src/commit/4b8169da286917fde7875425bb32b799b12c6af3/configuration_inspection.go),
and [inspection types](https://gitea.maximumdirect.net/eric/promptkit/src/commit/4b8169da286917fde7875425bb32b799b12c6af3/types.go).

View File

@@ -1,14 +1,12 @@
# Developing CommandKit
CommandKit currently contains adopted repository policies, accepted architectural
decisions, identity and outcome primitives, typed command
declarations, an instance-owned registry, a Cobra-backed routing and parsing
adapter, public `App.Execute` coordination, and generated help/version commands.
Configuration suite registration, scope discovery, ConfigKit validation and
reports, PromptKit engine configuration inspection, and optional PromptKit
prompt/profile inspection commands are implemented. The maintained
[consumer guide](consumers/guide.md) links to maintained examples. The
[README](../README.md) provides project orientation; the
CommandKit is distributed as a core Go module and two optional integration
modules. Core owns captured declarations, typed input preparation, installation,
dispatch, outcomes, help, and version. `integrations/ckconfig` owns ConfigKit
scope adaptation and reports; `integrations/ckprompt` owns PromptKit engine and
definition inspection adapters. The maintained
[consumer guide](consumers/guide.md) links to the three maintained consumers.
The [README](../README.md) provides project orientation; the
[documentation policy](policy/documentation.md#canonical-ownership) assigns
canonical documentation owners.
@@ -48,11 +46,11 @@ canonical documentation owners.
| Task | Read |
| --- | --- |
| Implemented CLI behavior | [CLI reference](cli.md) |
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [configuration declarations](../config.go), [PromptKit declarations](../promptkit.go), and applicable ADRs |
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs |
| Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
| Backend integration | [Internal overview](internal/overview.md), [adapter implementation](../internal/cobra/parse.go), and [ADR 0002](adr/0002-cobra-backend.md) |
| Public facade or adapter boundaries | [Internal overview](internal/overview.md), [ADR 0003](adr/0003-public-facade.md) as scoped by [ADR 0010](adr/0010-optional-integration-modules.md), and the architecture policy |
| Optional integration module transition and finalized API | [Module roadmap](roadmap/modules.md), [registration API target](roadmap/registration-api.md), and [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
| Module ownership and public contracts | [Consumer guide](consumers/guide.md), [internal overview](internal/overview.md), [core GoDoc](../doc.go), [ckconfig GoDoc](../integrations/ckconfig/doc.go), [ckprompt GoDoc](../integrations/ckprompt/doc.go), and applicable ADRs |
| Deferred capabilities and proposals | [Deferred work](roadmap/deferred.md) |
| Completed planning and implementation history | [Retired records in Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap) |
| Release tooling | [Maintainer release procedure](release.md) |
@@ -89,8 +87,25 @@ Sibling-checkout references in retired planning records are historical review
evidence, not build dependencies. Implemented contracts belong in CommandKit
under their canonical owners.
Run `go test ./...` from the repository root to compile the module and run its
deterministic tests. Format changed Go files with `gofmt`. The
The root module does not traverse nested modules. During development, use a
local workspace for all three modules; it is ignored and must not be committed.
If a local `go.work` already exists, preserve it and add these module directories:
```sh
if [ -f go.work ]; then
go work use . ./integrations/ckconfig ./integrations/ckprompt
else
go work init . ./integrations/ckconfig ./integrations/ckprompt
fi
go test ./...
(cd integrations/ckconfig && go test ./...)
(cd integrations/ckprompt && go test ./...)
```
The workspace checks package behavior. Workspace-off checks with each module's
own dependency graph are separate evidence; follow the roadmap's disposable
module-file procedure when future CommandKit versions are not published.
Format changed Go files with `gofmt`. The
[maintainer release procedure](release.md) owns candidate preparation and
publication commands.
@@ -112,15 +127,15 @@ or publishing.
## Current public examples
The maintained consumers under `examples/` compile with the module suite and
run without external services:
The maintained consumers compile with their owning module suites and run without
external services:
```sh
go run ./examples/simple config show
go run ./examples/simple greet --count=0 --tag=first --tag second
go run ./examples/composed config validate --scope all --campaign spring
go run ./examples/composed promptkit show prompt briefing --campaign spring --format yaml
go run ./examples/composed session restore session-42 --campaign spring
go run ./examples/core greet --count=0 --tag=first --tag second
(cd integrations/ckconfig/examples/simple && go run . config show)
(cd integrations/ckprompt/examples/composed && go run . config validate --scope all --campaign spring)
(cd integrations/ckprompt/examples/composed && go run . promptkit show prompt briefing --campaign spring --format yaml)
(cd integrations/ckprompt/examples/composed && go run . session restore session-42 --campaign spring)
```
The [consumer guide](consumers/guide.md) explains how their public API usage

View File

@@ -1,51 +1,70 @@
# Internal package overview
CommandKit ships one public package, `commandkit`, and one internal package,
`internal/cobra`. This inventory describes the current implementation; the
[architecture policy](../policy/architecture.md) owns normative boundaries and
[ADR 0003](../adr/0003-public-facade.md) records the original facade decision.
[ADR 0010](../adr/0010-optional-integration-modules.md) now scopes that decision to
the core and optional integrations; the [module roadmap](../roadmap/modules.md)
tracks the pending transition. The inventory below describes the prototype.
CommandKit's core module contains the public `commandkit` facade, the private
neutral metadata package, and the internal Cobra adapter. Two nested Go modules
own the optional ConfigKit and PromptKit integrations. The
[architecture policy](../policy/architecture.md) owns normative boundaries;
this page inventories the implemented owners.
## `commandkit`
## Root `commandkit`
The root package declares the public API and owns the instance registry, typed
command input preparation, invocation coordination, standard handlers, and
provider adapters. Configuration reports adapt ConfigKit's public records and
writers. PromptKit scope and definition handlers use PromptKit's public
inspection methods and map their results to CommandKit-owned reports.
The root facade owns captured command declarations, binding conversion,
invocation coordination, the per-App registry, standard help/version commands,
and outcome/diagnostic delivery. Its dependency graph has no ConfigKit or
PromptKit integration dependency. Applications provide typed callbacks and
choose when to install declarations.
The root lazily caches one immutable neutral bridge tree per `App`, invalidating
it after successful nonempty registration. For each `Execute`, it prepares one
adapter session and reuses that session for parsing, help, and usage. If a
callback registers commands during execution, metadata-dependent presentation
refreshes without repeating input callbacks. The root still prepares typed
input, invokes application/standard handlers, and coordinates outcomes and
diagnostic delivery. Application callbacks and their supported error identity
are handled in the root through its typed contracts.
The shared command compiler prepares supplied values before constructing input.
The batch installer validates retained issues, placement, and collisions before
mutating the registry. Each invocation uses one routing snapshot and backend
session; a successful registration invalidates the snapshot for a later
invocation. The root package owns app input and callback execution, not provider
configuration semantics.
Configuration registration owns and normalizes its declarations, then prepares
ordered scopes, name lookup, installed operations, and a discovery DTO. Command
handlers reuse that private metadata; each invocation still creates its context
and invokes acquisition only for selected scopes.
## `internal/commandmeta`
This package owns the private neutral command, flag, argument, parsed-value, and
failure records shared between the public facade and backend adapter. It does
not import Cobra or optional integration modules. The facade and adapter
exchange these records without exporting backend-specific types.
## `internal/cobra`
This package owns the Cobra-specific command tree, argument/flag parsing,
and help rendering. A session owns one mutable backend tree for an invocation;
parsing and presentation reuse it. Backend commands map directly to neutral
declarations, and Cobra parent links reconstruct only the selected command path.
The adapter returns raw parsed values and neutral syntax-failure data consumed
by the root package. It does not import `commandkit` and does not own registry
policy, public command declarations, provider loading, or standard inspection
report rendering.
This package owns the Cobra command tree, argument/flag parsing, and help
rendering. A session owns the mutable backend tree for one invocation; parsing
and presentation reuse that session. The adapter returns raw values and neutral
syntax failures to core. It does not own the registry, typed input preparation,
integration declarations, provider acquisition, or native report rendering.
Cobra and pflag imports remain inside this package.
## External implementation boundaries
## Optional modules
ConfigKit owns typed configuration loading, source history, validation,
resolution, and path explanations. PromptKit owns captured engine
configuration, prompt definitions, profile inheritance, and named inspections.
CommandKit depends on their public module APIs and does not maintain parallel
schemas. Cobra and pflag are confined behind the internal adapter; YAML report
encoding is performed by the root package.
`integrations/ckconfig` owns ConfigKit adaptation, scope capture, the standard
`config` command family, and native validate/show/sources/explain reports. It
depends on the public core facade and ConfigKit; it does not depend on PromptKit.
Each selected scope receives an independently initialized input, while one
suite-owned state value is shared by selected acquisitions in that invocation.
`integrations/ckprompt` owns PromptKit engine loading, configuration-scope
adaptation, and optional named prompt/profile inspection. It uses public core
and ckconfig contracts plus PromptKit's public APIs. It does not add a
configuration family when its declaration is installed; callers compose
`ckprompt.ConfigScope` with `ckconfig.Command` separately when they want both.
The three maintained consumers live at `examples/core`,
`integrations/ckconfig/examples/simple`, and
`integrations/ckprompt/examples/composed`. The
[consumer guide](../consumers/guide.md) links to those examples and explains the
public wiring. Run tests from each module; root `./...` does not traverse the
nested module directories. The [development guide](../development.md) gives the
workspace test commands. Workspace builds do not establish independent module
graph isolation.
## Upstream implementation boundaries
ConfigKit owns configuration decoding, validation, source history, and path
explanations. PromptKit owns its captured engine configuration, prompt
definitions, profile inheritance, and named inspection semantics. CommandKit
adapts those public contracts without maintaining parallel schemas or invoking
prompt execution. Application loaders and domain behavior remain application
owned.

View File

@@ -213,3 +213,42 @@ License and notices: [CC BY-SA 4.0](licenses/CC-BY-SA-4.0.txt) |
[Source](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843).
[Source](https://gitea.maximumdirect.net/eric/policy/src/commit/e833faddf120c789a9b45348edaf75720de16348).
## ReleaseKit
Selected module: `gitea.maximumdirect.net/eric/ReleaseKit` at `v0.4.0` (selected Go tool; not a runtime import).
Copyright (C) 2026 Eric Rakestraw
SPDX-License-Identifier: LGPL-3.0-or-later
License and notices: [LGPL v3.0](../../LICENSE) |
[LICENSE](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/LICENSE).
[Source](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b).
## Goldmark
Selected module: `github.com/yuin/goldmark/v2` at `v2.1.6` (ReleaseKit tool dependency).
Copyright (c) 2019 Yusuke Inuzuka
SPDX-License-Identifier: MIT
License and notices: [MIT](licenses/MIT.txt) |
[LICENSE](https://github.com/yuin/goldmark/blob/a8d4ee5a0bd7d5493fdd1e339b4e75df92f8684c/LICENSE).
[Source](https://github.com/yuin/goldmark/tree/a8d4ee5a0bd7d5493fdd1e339b4e75df92f8684c).
## Go modules
Selected module: `golang.org/x/mod` at `v0.40.0` (ReleaseKit tool dependency).
Copyright 2009 The Go Authors.
SPDX-License-Identifier: BSD-3-Clause
License and notices: [BSD 3-Clause](licenses/BSD-3-Clause.txt) |
[LICENSE](https://go.googlesource.com/mod/+/d3398d06de5fa5c71083d3d1c26f2cda73508e0f/LICENSE).
[Source](https://go.googlesource.com/mod/+/d3398d06de5fa5c71083d3d1c26f2cda73508e0f).

View File

@@ -21,12 +21,14 @@ policy and link to it rather than introduce additional release requirements.
## CommandKit Release Scope
CommandKit releases source-only Go modules. Standard CLI behavior is exposed by
consuming applications; CommandKit does not declare binary deliverables or a
cross-platform build matrix. ReleaseKit v0.3.0 is selected as the maintainer
publication tool. The [release procedure](../release.md) owns its source-only
workflow and repository-specific commands; the integration adds no application
command family or runtime ReleaseKit import.
CommandKit independently versions three source-only Go modules: the root core,
`integrations/ckconfig`, and `integrations/ckprompt`. Standard CLI behavior is
exposed by consuming applications; CommandKit does not declare binary
deliverables or a cross-platform build matrix. ReleaseKit v0.4.0 is selected as
the maintainer publication tool. The [release procedure](../release.md) owns
the selected-module workflow, release order, and repository-specific commands;
the integration adds no application command family or runtime ReleaseKit
import.
## Release Model And Completion

View File

@@ -1,47 +1,46 @@
# CommandKit release procedure
## Scope and prerequisites
## Scope and release order
CommandKit publishes source-only Go module releases: an immutable annotated
version tag for one committed candidate and its matching checked-in release
note. This procedure does not publish a hosted release page, binaries,
checksums, or other delivery assets, and it requires no delivery credentials.
CommandKit publishes source-only Go module releases. Each module has an
independent version and immutable annotated tag. This procedure publishes no
hosted release page, binaries, checksums, or other delivery assets. A successful
source-tag push is release completion; CI, module proxy availability, and
consumer installation are not completion gates.
Use branch `main`, remote `origin`, and the expected effective push endpoint
`https://gitea.maximumdirect.net/eric/CommandKit.git`. The profile enforces that
endpoint during publication. The maintainer needs the selected
[release toolchain](#release-toolchain), Git with push access to `origin`, and a
POSIX shell.
Publish in dependency order: core, then `ckconfig`, then `ckprompt`. The
integration modules require the preceding CommandKit releases, so prepare and
publish each module only after its CommandKit dependencies are available. A root
release runs only the root module's default suite; it need not run suites for
independently released integrations.
This procedure follows the [release policy](policy/release.md); the release-note
footer follows the [OSS discoverability policy](policy/oss.md#discoverability).
Use branch `main`, remote `origin`, and expected effective push endpoint
`https://gitea.maximumdirect.net/eric/CommandKit.git`. The selected module profile
enforces the endpoint. The maintainer needs the selected
[release toolchain](#release-toolchain), Git push access, and a POSIX shell.
This procedure follows the [release policy](policy/release.md); release-note
footers follow the [OSS discoverability policy](policy/oss.md#discoverability).
ReleaseKit v0.3.0 owns candidate validation, publication guards, annotated tag
creation, tag publication, and outcome reporting. The repository profile selects
only its default candidate suite. The launcher bootstraps the module-selected
native executable into ignored `.releasekit/` storage and invokes its `publish`
command. The upstream [CLI reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e43df4416e0ed987349b2ea04a2c68c25e552772/docs/cli.md),
[profile reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e43df4416e0ed987349b2ea04a2c68c25e552772/docs/config.md),
and [publication guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e43df4416e0ed987349b2ea04a2c68c25e552772/docs/consumers/publish.md)
own detailed command, profile, and status contracts.
ReleaseKit v0.4.0 owns candidate validation, publication guards, tag creation,
tag publication, and outcome reporting. Its pinned public contracts are the
[CLI reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/cli.md),
[profile reference](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/config.md),
and [publication guide](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/b96262eb0ce9c8f2eb3e948a5841db2b799bc91b/docs/consumers/publish.md).
The repository selects one default module suite per invocation. The launcher
bootstraps the native tool into ignored `.releasekit/` storage and delegates to
its `publish` command.
## Release toolchain
The selected release toolchain is **Go 1.26.8**. The consumer minimum is
**Go 1.26.0**; validation uses a later patch within that supported Go series.
The [consumer guide](consumers/guide.md#go-compatibility) explains the minimum and
its shared tool-module requirement; the
[release policy](policy/release.md#consumer-minimum-and-release-toolchain) governs
changes to either selection.
The selected release toolchain is **Go 1.26.8**. Each module declares a consumer
minimum of **Go 1.26.0**. Maintainers use Go 1.26.8 for dependency preparation,
candidate validation, and the ReleaseKit bootstrap. The
[consumer guide](consumers/guide.md#go-compatibility) and
[release policy](policy/release.md#consumer-minimum-and-release-toolchain)
describe these selections.
Use this toolchain for candidate validation and the native ReleaseKit bootstrap,
including CI jobs that perform those tasks. The launcher and ReleaseKit invoke
`go` from `PATH` with `GOTOOLCHAIN=local`, so select that installation in the
shell used for preparation and publication.
If it is not installed, use the [standard Go installation method](https://go.dev/doc/manage-install).
Ensure Go's executable installation directory (`GOBIN`, or `GOPATH/bin` by
default) is on `PATH` so the downloaded-version wrapper can be invoked:
Select Go 1.26.8 on `PATH`; the launcher uses `GOTOOLCHAIN=local`. If needed,
install it with the standard Go tools:
```sh
GOWORK=off GOTOOLCHAIN=local go install golang.org/dl/go1.26.8@latest
@@ -51,115 +50,75 @@ hash -r
GOWORK=off GOTOOLCHAIN=local go version
```
The final command should identify Go 1.26.8. An existing Go 1.26.8 installation
may be selected directly on `PATH` instead. Toolchain installation and dependency
preparation precede the offline publication checks; they add no validation pass.
## Modules, versions, notes, and shared files
## Prepare and publish a candidate
Select exactly one module with the launcher:
Choose a fresh, unused stable Semantic Version tag in the form
`vMAJOR.MINOR.PATCH`, with no leading zeroes. Before `v1.0.0`, a minor release
may change a documented contract if its note explains the impact and consumer
action; a patch release must not intentionally break contracts within its
minor line. Never reuse a version previously published through any release
channel. The first version is selected during release preparation, not embedded
in the tool or profile.
| Selector | Physical module directory | Release note | Full tag | Shared project files |
| --- | --- | --- | --- | --- |
| `core` | repository root | `docs/releases/<version>.md` | `<version>` | root `COPYRIGHT`, `LICENSE`, `docs/oss/attribution.md` |
| `ckconfig` | `integrations/ckconfig` | `integrations/ckconfig/docs/releases/<version>.md` | `integrations/ckconfig/<version>` | that module's `COPYRIGHT`, `LICENSE`, `docs/oss/attribution.md` |
| `ckprompt` | `integrations/ckprompt` | `integrations/ckprompt/docs/releases/<version>.md` | `integrations/ckprompt/<version>` | that module's `COPYRIGHT`, `LICENSE`, `docs/oss/attribution.md` |
Start from `main` and prepare a note at `docs/releases/<version>.md`. Begin with
a heading containing `CommandKit` and the exact version. Include a useful
summary and any compatibility impact or upgrade instructions. End it with the
license and attribution links at that version's immutable source tag, replacing
`VERSION` with the selected tag:
Use a fresh stable semantic version (`vMAJOR.MINOR.PATCH`) for the selected
module. Before `v1.0.0`, a minor release may change a documented contract when
its note explains the impact and consumer action. Never reuse a published
version. Each release note starts with a product title and exact version, gives
a proportionate summary and compatibility guidance, and ends with immutable
links to that module's local grant, license, and attribution paths. The full tag
in each URL includes the integration directory where applicable. Future tag
URLs need not resolve before publication.
```markdown
[COPYRIGHT](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/COPYRIGHT) |
[LICENSE](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/LICENSE) |
[ATTRIBUTION](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/VERSION/docs/oss/attribution.md)
```
Root publication validates root shared files. Integration publication validates
the matching module-local files; it does not substitute root-only notices. The
module release profiles select their physical module directory while using the
same repository and publication endpoint.
Review these paths in the candidate; the future tag URLs do not need to resolve
before publication.
## Prepare and publish one candidate
Prepare dependencies separately from the offline candidate suite:
Prepare dependencies in the selected module before the candidate is finalized.
Do this after the preceding CommandKit module has been published and before the
selected candidate suite is run. For `core`, run the command at the repository
root; for integrations, run it from that module directory. Commit any resulting
`go.mod` or `go.sum` changes with the release candidate. The sum files must
reflect dependencies actually downloaded for that module; do not fabricate
future sums.
Run these commands in the same shell session so the version variable remains
set:
```sh
commandkit_version=vX.Y.Z
GOWORK=off GOTOOLCHAIN=local go mod download
```
If dependency preparation changes `go.mod` or `go.sum`, review and commit those
changes with the candidate. Commit the note and all candidate changes on `main`,
then publish that commit to `origin`:
Then commit the selected module's release note and all intended candidate
changes on `main`, and publish the candidate commit to `origin`. Set one
selector, module directory, and version from the table above, then run:
```sh
module_dir=.
module_selector=core
module_version=v0.2.0
(cd "$module_dir" && GOWORK=off GOTOOLCHAIN=local go mod download)
# Commit reviewed dependency changes and the selected module's note on main.
git push origin HEAD:refs/heads/main
./scripts/release "$commandkit_version"
./scripts/release "$module_selector" "$module_version"
```
The launcher builds the ReleaseKit version selected by the module in readonly
mode. After preflight, `publish` runs the offline default Go suite once, checks
the candidate and remote guards, creates an annotated tag from the committed
note, and pushes only that tag object. The launcher does not push `main`; push
the candidate first. `check` is available for optional diagnosis and is not a
required step before `publish`. The automated publication workflow runs the
final-candidate suite once; configured additional checks should avoid duplicating
that suite. Maintainers may rerun diagnostics when useful. Successful source
publication does not wait for CI, module availability, or consumer installation.
Run only the command for the selected module. Its profile runs the complete
offline deterministic default suite once for that module, checks candidate and
remote guards, creates the annotated tag from the matching note, and pushes
only that full tag. `check` is available for diagnosis and is not a required
pre-publication command. The launcher does not push `main`; publish the
candidate commit first. Successful source publication does not wait for CI,
proxy availability, or downstream installation.
## Completion and statuses
## Completion and ambiguous publication
Publication is complete when the intended annotated tag is successfully pushed
to the expected endpoint, or when an exact tag-object query confirms that push
after an error. Status 0 reports confirmed publication. Status 1 reports a
known failure or conflict; status 2 reports invalid input or profile; status 3
means the push outcome remains unresolved. See the upstream [CLI status
contract](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e43df4416e0ed987349b2ea04a2c68c25e552772/docs/cli.md).
A successful push to the expected endpoint completes the source release. On an
ambiguous result, use the exact endpoint, full tag, and annotated tag object
reported by that invocation. Confirm endpoint resolution has not changed, then
query only that exact tag ref. Compare the remote annotated tag-object ID with
the reported object: an exact match confirms publication, a different object is
a conflict, successful output without the ref proves absence at that endpoint,
and a failed query leaves the result unresolved. Do not infer the captured
endpoint's state from another remote or a rewritten URL.
For a failed or ambiguous push, use the exact endpoint, version, and annotated
tag object reported by the invocation. Confirm that Git still resolves the
captured endpoint to itself before querying only that tag ref:
```sh
releasekit_endpoint='COPY THE CAPTURED ENDPOINT EXACTLY'
releasekit_version='vX.Y.Z'
releasekit_tag_object='COPY THE REPORTED TAG OBJECT ID'
releasekit_ref="refs/tags/$releasekit_version"
releasekit_resolved_endpoint=$(git ls-remote --get-url -- "$releasekit_endpoint") || {
printf '%s\n' 'publication state is unresolved: endpoint resolution failed' >&2
exit 1
}
if [ "$releasekit_resolved_endpoint" != "$releasekit_endpoint" ]; then
printf '%s\n' 'publication state is unresolved: endpoint resolution changed' >&2
exit 1
fi
releasekit_remote_tag=$(git ls-remote --refs -- "$releasekit_endpoint" "$releasekit_ref") || {
printf '%s\n' 'publication state is unresolved: remote query failed' >&2
exit 1
}
printf '%s\n' "$releasekit_remote_tag"
```
`--refs` returns the annotated tag object's ID, not its peeled commit. Compare
that ID with `releasekit_tag_object`: an exact match confirms publication; a
different object is a conflict; successful output with no matching ref proves
absence at the captured endpoint. A failed query or changed URL resolution is
unresolved, never evidence of absence. Do not query a different fetch URL or
follow a rewritten endpoint to infer the captured destination's state.
ReleaseKit retains a local tag after a failed push, so the tag blocks an ordinary
retry. After proving the tag absent at the captured endpoint,
confirm that it was never published or used by another release channel before
deliberately removing the unpublished local tag:
```sh
git tag -d "$releasekit_version"
```
Do not move, overwrite, recreate, or delete a published tag. If the exact tag
object is present remotely, keep it. Resolve conflicts with a fresh version;
corrections to published source require a new version. A transport failure
alone does not require a new version.
ReleaseKit may retain a local tag after a failed push. Remove an unpublished
local tag only after proving absence at the captured endpoint and confirming
that the tag was never published or used by another release channel. Never
move, overwrite, recreate, or delete a published tag. Resolve conflicts with a
fresh version; corrections to published source require a new version.

20
docs/releases/v0.2.0.md Normal file
View File

@@ -0,0 +1,20 @@
# CommandKit v0.2.0
This release replaces the earlier core registration and integration surface with
captured `commandkit.Command` declarations and batch installation through
`commandkit.New` or `App.Register`. This is an incompatible core API change;
consumers must update their declarations and installation wiring to the current
API. No compatibility layer is provided.
ConfigKit and PromptKit support is now provided by independently versioned
optional modules: `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig`
and `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt`. Applications
that need those integrations add their imports and install the returned
commands explicitly. The core module does not depend on either integration.
See the [consumer guide](../consumers/guide.md) and the
[CLI reference](../cli.md) for current contracts.
[COPYRIGHT](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/v0.2.0/COPYRIGHT) |
[LICENSE](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/v0.2.0/LICENSE) |
[ATTRIBUTION](https://gitea.maximumdirect.net/eric/CommandKit/src/tag/v0.2.0/docs/oss/attribution.md)

View File

@@ -1,6 +1,6 @@
# Implement the optional integration modules and captured registration API
Status: implementation in progress. Stages 1 through 14 are complete; subsequent work follows the ordered roadmap.
Status: implementation in progress. Stages 1 through 15 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.
@@ -751,10 +751,21 @@ its own usable licensing and release material.
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.
**Completion evidence — complete:** the three package GoDoc surfaces and current
consumer, CLI, internal, and development guides describe the captured factories,
module ownership, retained errors, input/state timing, and explicit installation.
Each integration has a module README, module-local `COPYRIGHT`/`LICENSE`, a
scoped attribution document, and local standard license texts. The LGPL/GPL
texts and copied license texts match the root texts; upstream entries use pinned
source revisions. The root attribution now identifies ReleaseKit v0.4.0 and its
direct tool dependencies. Release policy and procedure agree on independent
module versions, full nested tags, module-local note paths and shared files,
core-to-ckconfig-to-ckprompt publication order, dependency preparation, and the
selected-module suite. The three notes have the required titles, compatibility
explanations, and immutable full-tag footers. Local links and whitespace checks
pass for Markdown prose; standard license texts remain byte-for-byte copies,
including upstream formatting. No future CommandKit version is claimed to be
available remotely, and no tag, push, or publication was performed.
## Stage 16: Validate the complete end state and finish the sprint