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

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