Refresh operator documentation and CLI help

This commit is contained in:
2026-11-07 23:31:14 +00:00
parent 69fe35c480
commit c648d1de33
24 changed files with 1088 additions and 812 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +1,46 @@
# Consumer guide
CommandKit is distributed as three Go modules. Start with the core and add an
integration module only when the application uses that library. Core and
compatible integration command factories return canonical `commandkit.Command` values.
Applications may install those alongside application-owned `RoutingRule`
declarations through `commandkit.New` or `App.Register`; routing rules are
installed at the application root, not as group children.
Start with core to build commands with typed inputs and shared output
formatting. Add an integration when your application uses ConfigKit or
PromptKit. The [core command example](#core-commands) below shows the basic
API; the [maintained examples](../../README.md#examples) show complete
applications.
## Module selection
| Import | Use when |
| --- | --- |
| `go.maximumdirect.net/commandkit` | The application needs typed command declarations and common CLI behavior. |
| `go.maximumdirect.net/ckconfig` | The application wants ConfigKit-backed configuration scopes and reports. |
| `go.maximumdirect.net/ckprompt` | The application wants PromptKit engine configuration/comparison, five catalogs, named inspection, requirements discovery, request validation, or native smoke testing. |
| `go.maximumdirect.net/commandkit` | You need commands, typed inputs, help, and common output handling. |
| `go.maximumdirect.net/ckconfig` | You want operators to view, validate, explain, and compare ConfigKit configuration. |
| `go.maximumdirect.net/ckprompt` | You want operators to inspect PromptKit resources, check and preview requests, or run smoke tests. |
Core v0.4.0 is published. The previously published matched releases are core
v0.3.0, ckconfig v0.2.0, and ckprompt v0.2.0.
The published ckconfig v0.3.0 uses ConfigKit v1.1.0 and does not compose
with ckprompt v0.2.0, which retains ckconfig v0.2.0 and ConfigKit v0.8.0.
Install the current core with `go get go.maximumdirect.net/commandkit@v0.4.0`.
For the older matched integration set, select core v0.3.0 and the corresponding
ckconfig or ckprompt v0.2.0 release together.
The following distinguishes published combinations from the current checkout:
Published ckconfig v0.4.0 uses core v0.4.0 and ConfigKit v1.1.0. The ckprompt
v0.3.0 candidate targets those releases and PromptKit v0.20.0. A Go 1.27.0
workspace may compose the three local modules. Current ckprompt source uses a
diagnostic helper introduced in local ckconfig source that is absent from
released ckconfig v0.4.0; independent ckprompt builds require release and
dependency alignment described in [future work](../roadmap/future.md#pending-release-and-integration-work).
| Selection | Core | ckconfig | ckprompt | Upstream libraries and status |
| --- | --- | --- | --- | --- |
| Published core | v0.4.0 | — | — | Usable independently. |
| Published ConfigKit integration | v0.4.0 | v0.4.0 | — | ConfigKit v1.1.0. |
| Earlier matched integration set | v0.3.0 | v0.2.0 | v0.2.0 | ConfigKit v0.8.0 and PromptKit v0.16.0, using their earlier import paths. |
| Current source | Local | Local | Local | ConfigKit v1.1.0 and PromptKit v0.20.0; use an aligned workspace until release dependencies are updated. |
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.
Install the published core with:
```sh
go get go.maximumdirect.net/commandkit@v0.4.0
```
Core v0.5.0 and ckprompt v0.3.0 have unpublished candidate notes. Current
ckprompt source calls `ckconfig.AdaptDiagnostics`, which is absent from its
selected released ckconfig v0.4.0 dependency. It therefore needs local
ckconfig source in the workspace until [release
alignment](../roadmap/future.md#pending-release-and-integration-work) is
complete. Published ckconfig v0.3.0 also uses ConfigKit v1.1.0 and does not
compose with ckprompt v0.2.0's earlier ConfigKit dependency.
Importing a module does not install its commands. Pass commands to
`commandkit.New` or `App.Register` explicitly. ckprompt depends on ckconfig's
public APIs, but you can install its `promptkit` commands without installing
the `config` family.
## Go compatibility
@@ -57,7 +63,6 @@ default from an explicitly supplied empty, false, or zero value.
package example
import (
"fmt"
"strconv"
commandkit "go.maximumdirect.net/commandkit"
@@ -81,8 +86,12 @@ func Greeting() commandkit.Command {
),
},
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
if _, err := fmt.Fprintln(invocation.Reporter().Output(), input.Count.Value); err != nil {
return commandkit.Failure("Could not write the greeting.").WithCause(err)
greetings := []string{}
for i := 0; i < input.Count.Value; i++ {
greetings = append(greetings, "Hello!")
}
if err := invocation.Reporter().Report(commandkit.Report{Value: greetings}); err != nil {
return commandkit.Failure("Could not write the greetings.").WithCause(err)
}
return commandkit.Success()
},
@@ -90,6 +99,10 @@ func Greeting() commandkit.Command {
}
```
Install `Greeting()` with `commandkit.New(identity, Greeting())`. By default,
`greet` prints `Hello!`; `greet --count=2` prints it twice. Add `--format
json` to receive a JSON list. A count of zero produces an empty list.
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
@@ -134,15 +147,13 @@ installation alongside aliases and integration commands.
## Invocation reporting
`Invocation.Reporter()` supplies the reporter for the current handler. Use
`Report()` for formatted substantive values and optional text templates;
use `Output()` or `RenderOutput()` for deliberate raw output. Use `Warn`, `Info`,
`Progress`, and `Debug` for categorized messages. Queue a summary with
`AtEnd().Info` when it belongs after the handler returns. Deferred submissions
are accepted until finalization begins; later submissions return
`ErrReporterClosed`. The
[CLI reference](../cli.md#reporting) owns flag grammar, visibility, prefixes,
and status behavior.
Use `Invocation.Reporter().Report` to print a value in the selected output
format. Pass ordinary Go values and, optionally, a `text/template` for text
output. Use `Warn`, `Info`, `Progress`, and `Debug` for categorized messages.
Queue a summary with `AtEnd().Info` when it belongs after the handler returns.
Deferred submissions are accepted until finalization begins; later submissions
return `ErrReporterClosed`. The [CLI reference](../cli.md#reporting) owns flag
grammar, visibility, prefixes, and status behavior.
Reports use JSON serialization to establish the common value representation
for YAML and JSON. A text template receives the original value; without one,
@@ -159,22 +170,29 @@ write to their supplied writer only while the callback runs; they must not
submit another message or start another rendering operation through the same
reporter.
For example, a handler can report a count as a small mapping:
```go
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
if _, err := fmt.Fprintln(invocation.Reporter().Output(), input.Count.Value); err != nil {
return commandkit.Failure("Could not write the greeting.").WithCause(err)
}
return commandkit.Success()
if err := invocation.Reporter().Report(commandkit.Report{
Value: map[string]int{"count": input.Count.Value},
}); err != nil {
return commandkit.Failure("Could not write the count.").WithCause(err)
}
return commandkit.Success()
```
This uses YAML automatically and supports `--format json` without a separate
encoder. Use `Output()` or `RenderOutput()` instead when you deliberately need
raw output; `--format` does not reformat those bytes.
After `App.Execute`, inspect the returned `Outcome`. Its `Cause` retains the
operation error; `Presentation.Output` and `Presentation.Diagnostics` report
delivery state and the first rendering or write errors for their destinations.
CommandKit does not retain a message transcript. Reporter operations for one
invocation are safe concurrently, but concurrent submission order is not
specified. The caller owns the writers passed to `Execute`; CommandKit does not
close them.
Joined operation errors support `errors.Is` and `errors.As` where the
underlying errors do. CommandKit does not retain a message transcript.
Reporter operations for one invocation are safe concurrently, but concurrent
submission order is not specified. The caller owns the writers passed to
`Execute`; CommandKit does not close them.
## Application-owned aliases
@@ -235,18 +253,22 @@ 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 or a custom comparison provider. A declared `Diff` capability
uses `Scope.Compare`; `ckconfig.FromConfigKit` and `AppCommand` provide the
ConfigKit-backed implementation. `Selector.AgainstName` opts a selector into an
independent right-side flag. Each comparison side gets its own initialized and
checked input, with only its supplied selectors applied; state is shared by the
invocation. Factory results
remain caller-owned, so separate initialization calls do not guarantee distinct
objects. See
acquisition state or a custom comparison provider. A declared `Diff`
capability uses `Scope.Compare`; `ckconfig.FromConfigKit` and `AppCommand`
provide the ConfigKit-backed implementation. `Selector.AgainstName` opts a
selector into an independent right-side flag. Each comparison side gets its
own initialized and checked input, with only its supplied selectors applied;
state is shared by the invocation. Factory results remain caller-owned, so
separate initialization calls do not guarantee distinct objects. See
[ckconfig.Suite's GoDoc](../../integrations/ckconfig/contracts.go) for factory
timing, omitted-factory zero values (including nil pointers), and ownership.
The application owns the state type and what it caches. `ckconfig.FromConfigKit`
adapts a typed ConfigKit loader without calling it during construction.
The application owns the state type and what it caches.
`ckconfig.FromConfigKit` adapts a typed ConfigKit loader without calling it
during construction. The bundled comparison adapters call the loader for the
left side before the right, retain left diagnostics if right loading fails,
and collect diagnostics from both loads before native comparison. Custom
comparison callbacks own their loading and diagnostics; loader calls need not
reread sources if the application caches them.
The `config` family provides scope discovery, validation, safe effective configuration display,
source inventory, path explanation, and ConfigKit-backed comparison for the
@@ -274,6 +296,8 @@ it does not install PromptKit catalog, definition, or requirements commands.
Its override feature is disabled because the released PromptKit configuration
loader does not accept ConfigKit override records.
### Install resource commands and optional checks
`ckprompt.FromEngine(loadEngine)` supplies nine callbacks: prompt, profile,
backend, namespace, and collection catalogs; named prompt, profile, and backend
inspection; and native requirements discovery. Concrete request validation,
@@ -308,6 +332,8 @@ suite := ckprompt.WithRequestValidation(
validationCommand := ckprompt.Command(suite)
```
### Request builders and loading
If the loader is nil, the returned suite retains a wiring issue for installation
to report, even if capabilities are narrowed later. A builder runs before the
engine loader and receives the seed request, selection, typed input, shared
@@ -357,6 +383,8 @@ same canonical request flags into their own input types. Each collection exposes
individual handles and an `All` method, so a command can choose its applicable
subset. The application decides how to apply the resulting values to its request.
### Enable namespace flags
`ckprompt.WithNamespaces` enables standard resource namespace selection from
application-supplied defaults. Loaders used with this option should leave view
selection to the adapter. Without it, a loader can supply its own engine view.

View File

@@ -62,7 +62,7 @@ capability proposals in [future work](roadmap/future.md).
| Public facade or adapter boundaries | [Internal overview](internal/overview.md), [ADR 0002](adr/0002-public-facade-and-cli-backend.md), [ADR 0004](adr/0004-optional-integration-modules.md), and the architecture policy |
| 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 |
| Unfinished work and capability proposals | [Future work](roadmap/future.md) |
| Documentation refresh sprint | [Documentation roadmap](roadmap/documentation-refresh.md) |
| Documentation refresh record | [Documentation roadmap](roadmap/documentation-refresh.md) |
| Completed planning and implementation history | [Completed dependency upgrades, PromptKit validation, discovery, smoke testing, and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/a6278a6d9f940948ec7745955d745523aaff0734/docs/roadmap), [earlier ConfigKit and PromptKit adoption and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/8a82620dfcd34c0ae56bbecb0d014eb49786bc92/docs/roadmap), [earlier retired records](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap), and [completed module implementation and remediation](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/bb2528532b78d30e52f5082e491a5e1fd9b0fb99/docs/roadmap) in Git history |
| Release tooling | [Maintainer release procedure](release.md) |
| Performance maintenance | [Internal overview](internal/overview.md), existing benchmarks, and [possible further efficiency work](roadmap/future.md#possible-further-efficiency-work) |
@@ -107,8 +107,16 @@ Sibling-checkout references in retired planning records are historical review
evidence, not build dependencies. Implemented contracts belong in CommandKit
under their canonical owners.
The root module does not traverse nested modules. Preserve the ignored `go.work`
and `go.work.sum`; use `GOWORK=off GOTOOLCHAIN=local` for dependency preparation
The root module does not traverse nested modules. With Go 1.27.0 on `PATH`,
create the local workspace from the repository root if `go.work` is absent:
```sh
go work init . ./integrations/ckconfig ./integrations/ckprompt
```
If a workspace already exists, ensure it includes these three modules. Preserve
the ignored `go.work` and `go.work.sum`; do not commit them. Use
`GOWORK=off GOTOOLCHAIN=local` for dependency preparation
and independent module suites. The integrations select released core v0.4.0;
ckprompt also selects released ckconfig v0.4.0.
Current ckprompt source requires a ckconfig helper absent from that release, so

View File

@@ -1,32 +1,28 @@
# CommandKit v0.5.0
CommandKit v0.5.0 fixes defects in deferred reporting and YAML value preservation,
reduces repeated work in command installation and alias help, and simplifies
typed input preparation and replay of captured flags.
CommandKit v0.5.0 fixes lost deferred messages and preserves YAML value types
more accurately. It also reduces repeated work when installing commands and
showing alias help, and refreshes documentation and help text.
## Changes
- Acceptance of deferred messages now closes atomically when invocation finalization
begins. Concurrent submissions are included in the final batch or rejected
with `ErrReporterClosed`; accepted messages can no longer be silently lost
between batch detachment and closure.
- Finalized reporting state releases its direct references to borrowed output
and diagnostic writers while retaining presentation results. Writers remain
caller-owned.
- `DecodeYAMLReport` follows resolved YAML scalar tags, preserving numeric-looking
strings as strings. YAML report rendering preserves explicit numeric meaning
for values beyond the resolver's ordinary numeric range.
- Compilation of flag aliases reuses resolved chain suffixes. Alias discovery and
help reuse the existing source tree, and declaration validation reuses one
scratch path across siblings, formatting paths only for diagnostics.
- Typed input preparation reconstructs occurrence order without general sorting;
replay of captured flags merges already ordered streams. Parsing and completion
share flag-consumption mechanics while retaining their distinct handling of
errors and incomplete input.
- The core reporting example preserves its default scenario when the optional
operand is omitted. The interactive completion fixture no longer collides with
the reserved `--format` flag. `FlagMeta` documentation now states the existing
naming and reserved-spelling rules.
- Deferred messages accepted before finalization are retained for final reporting;
they can no longer be silently lost when a handler finishes. Later submissions return
`ErrReporterClosed`.
- Finished invocations release their direct references to output and diagnostic
writers while keeping delivery results available. Applications still own the
writers.
- `DecodeYAMLReport` preserves numeric-looking strings as strings. YAML report
output also preserves explicitly tagged numbers beyond the YAML resolver's
ordinary numeric range.
- Command installation, alias help, and typed input handling avoid repeated
work. Parsing and completion share flag handling while retaining their
different treatment of errors and unfinished input.
- The reporting example now works when its optional scenario is omitted, and
the interactive completion fixture no longer conflicts with `--format`.
`FlagMeta` documents existing naming and reserved-spelling rules.
- READMEs, CLI instructions, examples, and generated help use clearer language
and explain common tasks before implementation details.
## Compatibility and upgrade

View File

@@ -1,7 +1,7 @@
# Documentation refresh
Status: agreed scope; ready for implementation planning. The refresh has not
been implemented.
Status: implemented and verified. Release/dependency alignment remains separate
work in [future.md](future.md#pending-release-and-integration-work).
## Purpose
@@ -197,18 +197,57 @@ Do not add wording snapshots, readability gates, or a new checker framework.
Record workspace and independent-module results separately, including any
dependency limitation. This work adds no release gates.
- [ ] README openings explain purpose and give a clear starting path.
- [ ] CLI sections explain operator tasks before reference detail; necessary
- [x] README openings explain purpose and give a clear starting path.
- [x] CLI sections explain operator tasks before reference detail; necessary
behavior, report fields, status rules, and limitations remain discoverable.
- [ ] Example setup is explicit, commands have nearby explanations, and intended
- [x] Example setup is explicit, commands have nearby explanations, and intended
failures are labeled.
- [ ] Consumer guidance demonstrates formatted reporting, has a coherent initial
- [x] Consumer guidance demonstrates formatted reporting, has a coherent initial
example, and distinguishes published compatibility from current source needs.
- [ ] Package introductions and generated help use clear, accurate language;
- [x] Package introductions and generated help use clear, accurate language;
precise API contracts remain intact.
- [ ] Unpublished release notes explain benefits and consumer impact while
- [x] Unpublished release notes explain benefits and consumer impact while
historical records and required notices remain preserved.
- [ ] Changed commands, snippets, and help have appropriate verification; local
- [x] Changed commands, snippets, and help have appropriate verification; local
links and Markdown whitespace checks pass.
- [ ] Final review confirms consistent terminology, canonical ownership, and no
- [x] Final review confirms consistent terminology, canonical ownership, and no
unintended behavior or contract changes.
## Implementation and verification
Completed the six work areas above. READMEs and package introductions now lead
with purpose and starting points; the CLI reference separates operator tasks
from report detail and developer wiring. Examples are grouped by task with
setup, expected results, and intentional failures explained nearby. The consumer
guide demonstrates shared report formatting and distinguishes published modules
from current source. Help strings and unpublished candidate notes use the same
plain language. Exact symbol contracts and runtime behavior were preserved.
Verification used Go 1.27.0 and existing cached dependencies:
- The aligned workspace suites passed for core, ckconfig, and ckprompt, including
their maintained examples.
- Independent core and ckconfig suites passed with `GOWORK=off`.
- Independent ckprompt compilation confirmed the existing dependency limitation:
released ckconfig v0.4.0 lacks `AdaptDiagnostics`. No module requirements,
checksums, or workspace files were changed to hide it. Its README, example,
consumer guidance, and candidate note identify the pending alignment.
- All 48 `go run` invocations in the three example READMEs were exercised with
binaries built from the aligned workspace, from the documented directories.
Results matched the walkthroughs, including two failed-load examples, missing
request input, and comparison status 3. Shared help and completion behavior
also passed the existing suites; representative rendered help was inspected.
- Both new consumer-guide report snippets compiled in a temporary consumer using
local core. Six checks confirmed greeting counts, empty-list output, and YAML
and JSON formatting.
- Local Markdown links, including incoming links to renamed sections, and
whitespace were checked. Go source changes are limited to help strings,
package comments, and formatting; no new tests or validation framework were
added.
- The authoritative remote had neither the core v0.5.0 nor ckprompt v0.3.0 tag
when their candidate notes were revised. Published notes, accepted ADRs,
policies, and license/attribution records were left intact.
The updated ckprompt candidate still requires dependency guidance to be finalized
when release alignment occurs. This is release preparation, not unfinished
editorial work or evidence of an independently buildable candidate.

View File

@@ -1,7 +1,7 @@
# Future work
Status: documentation refresh, pending release/dependency alignment, optional
shell validation, and future capability proposals.
Status: pending release/dependency alignment, optional shell validation, and
future capability proposals.
No delivery dates are selected here.
## Purpose and authority
@@ -30,13 +30,6 @@ an idea here does not select its syntax, API, priority, or delivery date.
## Pending release and integration work
### Documentation refresh
The agreed [documentation roadmap](documentation-refresh.md) owns the upcoming
clarity refresh, its scope, sequence, and completion checklist. The work covers
operator instructions and public introductions while retaining necessary
technical detail in developer documentation.
### Audit remediation release alignment
The audit remediation is complete in source. The released ckconfig v0.4.0 does