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

View File

@@ -1,26 +1,22 @@
# CommandKit
CommandKit is a Go library for typed command declarations, shared CLI behavior,
and application-owned execution. The core `commandkit` module is usable by
itself. ConfigKit and PromptKit support lives in separately versioned optional
modules, so applications choose which upstream libraries they add.
CommandKit helps Go applications build consistent command-line interfaces. It
provides typed flags and arguments, help, output formatting, and error reporting.
Optional integrations add commands for inspecting configuration and working with
PromptKit.
The core captures reusable command declarations, validates installation batches
before changing an application's registry, converts typed inputs before
constructing them, and returns outcomes without exiting the process. Its
[consumer guide](docs/consumers/guide.md) covers declaration, invocation
and reporting. Each handler receives one invocation reporter for
substantive output, categorized messages, and terminal explanations; `Execute`
returns delivery observations with the outcome. The [CLI reference](docs/cli.md)
defines the shared visibility policy.
CommandKit is in alpha. Start with the [consumer guide](docs/consumers/guide.md#core-commands)
to define a command, or run the [core example](examples/core/README.md).
Applications supply their own command handlers and decide when to exit;
CommandKit returns the result of each invocation.
## Modules
| Module | Package | Provides |
| --- | --- | --- |
| `go.maximumdirect.net/commandkit` | `commandkit` | Typed commands, bindings, execution reporting and outcomes, help, and version. |
| `go.maximumdirect.net/ckconfig` | `ckconfig` | ConfigKit-backed `config` scopes, including configuration source evidence. |
| `go.maximumdirect.net/ckprompt` | `ckprompt` | PromptKit engine configuration/comparison, five catalogs, named inspection, requirements discovery, concrete request validation, and native smoke tests. |
| `go.maximumdirect.net/commandkit` | `commandkit` | Commands, typed inputs, shared output and error reporting, help, and version. |
| `go.maximumdirect.net/ckconfig` | `ckconfig` | Commands to view, validate, explain, and compare ConfigKit configuration. |
| `go.maximumdirect.net/ckprompt` | `ckprompt` | Commands to list and inspect PromptKit resources, discover required inputs, validate and preview requests, and run smoke tests. |
Importing an integration does not install commands. Core and the integrations
are versioned separately; see the [consumer guide](docs/consumers/guide.md#module-selection)

View File

@@ -32,8 +32,8 @@ func (a *App) builtinCommands() []Declaration {
help := captureCommand(CommandSpec[helpInput]{
Name: "help",
Summary: "Show help for commands.",
Description: "Describe registered commands and their inputs.",
Arguments: []Argument[helpInput]{RepeatArgument(ArgumentMeta{Name: "COMMAND", Usage: "registered command path"}, 0, -1,
Description: "Show available commands, flags, and arguments.",
Arguments: []Argument[helpInput]{RepeatArgument(ArgumentMeta{Name: "COMMAND", Usage: "Command path to describe."}, 0, -1,
func(value string) (string, error) { return value, nil },
func(input *helpInput, value Supplied[[]string]) { input.Targets = value })},
}, func(current commandExecution, input helpInput) Outcome {
@@ -43,9 +43,9 @@ func (a *App) builtinCommands() []Declaration {
version := NewCommand(CommandSpec[versionInput]{
Name: "version",
Summary: "Show application or CommandKit version.",
Description: "Report identity and build metadata without loading application configuration.",
Description: "Show the name, version, and revision without loading application configuration.",
Flags: []Flag[versionInput]{
ValueFlag(FlagMeta{Name: "scope", Usage: "version subject", Completion: CompleteChoices(CompletionChoice{Value: "app"}, CompletionChoice{Value: "commandkit"})}, &scopeDefault, parseVersionScope, func(input *versionInput, value Supplied[string]) { input.Scope = value.Value }),
ValueFlag(FlagMeta{Name: "scope", Usage: "Show the app or CommandKit version.", Completion: CompleteChoices(CompletionChoice{Value: "app"}, CompletionChoice{Value: "commandkit"})}, &scopeDefault, parseVersionScope, func(input *versionInput, value Supplied[string]) { input.Scope = value.Value }),
},
Run: func(invocation Invocation, input versionInput) Outcome {
identity := a.identity

16
doc.go
View File

@@ -1,8 +1,10 @@
// Package commandkit provides the core instance-owned CLI dispatcher, typed
// command declarations, application-owned command and flag aliases, input
// bindings, invocation-scoped reporting, and outcomes with separate operation
// causes and presentation observations. New and App.Register accept canonical
// Command declarations and RoutingRule declarations together. Optional
// integration modules provide ConfigKit and PromptKit-specific commands;
// importing those modules does not install their commands.
// Package commandkit helps Go applications build consistent command-line
// interfaces with typed flags and arguments, help, and shared output formatting.
// Define commands with NewCommand and install them with New or App.Register.
// Commands and command or flag aliases can be installed together.
//
// App.Execute runs a command and returns an Outcome; the application decides
// when to exit. Handlers use Invocation.Reporter for output and messages.
// Optional ckconfig and ckprompt modules add inspection and testing commands;
// applications install those commands explicitly.
package commandkit

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

View File

@@ -1,38 +1,70 @@
# Core example
Run the example from the repository root:
This example shows typed flags, command shortcuts, shared reporting, and shell
completion. It needs no external service. See the [consumer guide](../../docs/consumers/guide.md#go-compatibility)
for Go requirements; maintainers use the toolchain in the
[developer guide](../../docs/development.md#documentation-validation).
Run from the repository root, with that Go toolchain on `PATH`:
```sh
export GOWORK=off GOTOOLCHAIN=local
go run ./examples/core workspace greet --count=2
```
The result shows the selected count and whether it was supplied. It also shows
the entered command path and the original command path, which differ when you
use a shortcut.
## Try shortcuts and explicit values
```sh
# The hello shortcut runs workspace greet; --times means --count.
go run ./examples/core hello --times=0 --tag=first
# ws is a shortcut for the workspace group.
go run ./examples/core ws greet --count=2
# Inspect the group or use the example's global help alias.
go run ./examples/core ws --help
go run ./examples/core hello --hlep
```
An explicit zero remains a supplied value. The handler prints both
`Invocation.EnteredPath()` and `Invocation.CanonicalPath()` so you can see how
shortcuts resolve.
## Try reporting
```sh
go run ./examples/core report
go run ./examples/core report --verbose
go run ./examples/core report --quiet
```
The default scenario succeeds and writes its result. Verbose mode also shows
warnings and information; quiet mode hides the result. The
[CLI reference](../../docs/cli.md#reporting) defines the shared visibility rules.
## Try shell completion
```sh
go build -o core-example ./examples/core
./core-example completion bash
```
The example installs a canonical `workspace greet` command together with a
command shortcut, a group shortcut, a scoped flag alias, and a global help
alias. Its declaration slice mixes the canonical group and routing rules as
`[]commandkit.Declaration`. The handler prints `Invocation.EnteredPath()` and
`Invocation.CanonicalPath()` so the alternate route and its canonical target
are visible in the output.
This prints the Bash completion script. Initialize `bash-completion`, then load
the script as described in the [CLI reference](../../docs/cli.md#shell-completion).
Use the executable basename `core-example` and try completing
`core-example report d` or `core-example ws gr`. Other supported shells are
listed in the reference.
The example also installs `Completion("core-example")` and gives the `report`
scenario argument static choices. Initialize `bash-completion` first if using
Bash. Build it with the basename shown above, load
the script for your shell using the [CLI reference](../../docs/cli.md#shell-completion),
and try completing `core-example report d` or `core-example ws gr`.
## How it is wired
Compatible integration factories also return `commandkit.Command` and can be
passed directly to `New` beside `commandkit.Alias` or flag-alias declarations.
The matched ckconfig and ckprompt releases use the new core identity. For a
command-only `[]commandkit.Command`, convert its elements into a
`[]commandkit.Declaration` before appending routing rules; Go cannot expand the
command slice as `...commandkit.Declaration`. The
The example installs `workspace greet` alongside command and flag aliases in a
`[]commandkit.Declaration`. It also installs `Completion("core-example")` and
provides static choices for the reporting scenario argument. The
[consumer guide](../../docs/consumers/guide.md#application-owned-aliases)
shows both forms, and the [composed consumer](../../integrations/ckprompt/examples/composed)
is the maintained integration example.
explains declaration composition; the [composed example](../../integrations/ckprompt/examples/composed)
adds integration commands.
These aliases require core v0.3.0. Repository contributors can run its test with
`go test ./examples/core` from the root.
Run `GOWORK=off GOTOOLCHAIN=local go test ./examples/core` from the repository
root to check this example.

View File

@@ -1,36 +1,30 @@
# CommandKit ckconfig
`ckconfig` is the optional ConfigKit integration for CommandKit. It adapts
ConfigKit loaders and scopes into reusable `commandkit.Command` declarations;
installing the integration is explicit and does not modify an application by
itself.
`ckconfig` adds configuration inspection commands to Go applications that use
CommandKit and ConfigKit. Operators can view settings, validate configuration,
find where values came from, and compare two configurations.
The application chooses which commands to install. Importing the package alone
does not install commands.
## Module
The module path is `go.maximumdirect.net/ckconfig`. Version v0.4.0 requires Go
1.27.0 and uses `go.maximumdirect.net/commandkit v0.4.0` and
`go.maximumdirect.net/configkit v1.1.0`; it does not import PromptKit. See the
[consumer guide](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/consumers/guide.md#configkit-scopes)
for exact callback and lifetime contracts.
The module path is `go.maximumdirect.net/ckconfig`. It does not import PromptKit.
See the [consumer guide](https://forge.maximumdirect.net/base-layer/commandkit/src/branch/main/docs/consumers/guide.md#module-selection)
for compatible releases and Go requirements.
## Example
For one application configuration scope, install the convenience declaration:
To inspect one application configuration, pass your loader to `AppCommand`:
```go
app, err := commandkit.New(identity, ckconfig.AppCommand(loadAppConfig))
```
Use `ckconfig.Command(ckconfig.Suite[Input, State]{...})` to define named
scopes, selectors, input checks, and state shared by the selected acquisitions
or comparison in a config invocation. `ckconfig.FromConfigKit` adapts a typed
ConfigKit loader. The `config` command family exposes scope discovery and the
validate, show, sources, explain, and diff operations supported by the declared
scopes. Source reports include native destination, placement, destination
fallback, version evidence, and empty-import selections. Comparison returns
ConfigKit's native records to shared report rendering; the
[CLI reference](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/cli.md#compare-configuration-selections)
owns its operator details.
For multiple named configurations or application-specific flags, use
`ckconfig.Command` with a `ckconfig.Suite`. The
[integration guide](https://forge.maximumdirect.net/base-layer/commandkit/src/branch/main/docs/consumers/guide.md#configkit-scopes)
explains loader setup, inputs, and shared state.
The maintained [simple example](examples/simple) shows a complete consumer.
The [CommandKit CLI reference](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/cli.md#configuration-scopes)

View File

@@ -1,10 +1,11 @@
// Package ckconfig, provided by go.maximumdirect.net/ckconfig, provides
// CommandKit's optional ConfigKit v1.1.0 integration, requiring Go 1.27.0. Its
// canonical Command declaration installs the standard config command family
// through the core commandkit package. Applications can install CommandKit
// RoutingRule declarations alongside it through commandkit.New or
// App.Register. Source reports preserve ConfigKit's destination, placement,
// version, and empty-import evidence. Invocation reporting applies CommandKit's shared
// visibility and delivery policy; provider warnings remain independent of
// failure explanations. Importing ckconfig alone installs no commands.
// Package ckconfig adds commands to view, validate, explain, and compare
// ConfigKit configuration in CommandKit applications.
//
// Use AppCommand for one application configuration loader, or Command with a
// Suite for multiple named configurations and application-specific flags.
// Install the returned command with commandkit.New or App.Register.
// Importing this package alone installs no commands.
//
// ConfigKit owns configuration loading and interpretation. CommandKit formats
// reports and messages using its shared reporting policy.
package ckconfig

View File

@@ -1,37 +1,90 @@
# Simple consumer
# ConfigKit example
This example imports `go.maximumdirect.net/ckconfig` and
`go.maximumdirect.net/commandkit`; ckconfig v0.4.0 uses core
v0.4.0, ConfigKit v1.1.0, and Go 1.27.0. Set `GOWORK=off GOTOOLCHAIN=local`
for the commands below.
This example adds configuration inspection and a custom `greet` command to a
small application. It uses local fixtures and in-memory defaults, with no
external services. See [module selection](../../../../docs/consumers/guide.md#module-selection)
for dependencies and Go requirements. Use Go 1.27.0 on `PATH` for this checkout.
Run the maintained example with:
From the repository root:
```sh
cd integrations/ckconfig/examples/simple
export GOWORK=off GOTOOLCHAIN=local
go run . config show
go run . config show --config fixtures/before.yml --verbose
go run . config show --config fixtures/before.yml --quiet
```
The output includes the default greeting, `Hello`, and schema version 2.
This example can run against its declared released dependencies with the
workspace disabled.
## Inspect and override a value
```sh
# Discover configuration paths under schema.
go run . config explain --list --under /schema
# Change the greeting for this invocation and show just that value.
go run . config show --path /greeting --set '/greeting="Hi"'
```
The second command prints `Hi`. It does not edit a file.
## Compare configurations
```sh
go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml
```
The report includes `changes.greeting: Goodbye`.
```sh
# Expected status 3: the overridden greeting differs from the ordinary default.
go run . config diff --set '/greeting="Hi"' --details --check
```
This compares the overridden left side with ordinary configuration on the
right. `go run` prints `exit status 3` and itself exits with status 1; a built
executable returns the application's status 3 directly.
## Inspect warnings and failed loads
```sh
# Schema version 1 produces a warning, visible in verbose mode.
go run . config show --config fixtures/before.yml --verbose
# Quiet mode hides the configuration report and warning.
go run . config show --config fixtures/before.yml --quiet
```
Ordinary mode hides the warning but still displays configuration.
```sh
# Intentional failure: show detailed validation findings for the invalid fixture.
go run . config validate --config fixtures/invalid.yml --details --severity error
# Intentional failure: still show the source recorded before loading failed.
go run . config sources --config fixtures/invalid.yml --source-id source-1
```
Both commands retain the load failure. `source-1` belongs to this fixture's
load; other configurations can have different source IDs. See the
[CLI reference](../../../../docs/cli.md#configuration-scopes) for report and status rules.
## Try a custom command
```sh
go run . greet
go run . greet --count=0 --tag=first --tag second
```
The `config` family comes from one typed ConfigKit scope. The custom `greet`
command uses CommandKit's typed bindings and shows the difference between an
omitted `--count` and an explicitly supplied zero, plus ordered repeated tags.
With no `--config`, application settings use the in-memory default. A supplied
configuration and overlay are passed to ConfigKit unchanged. The comparison
command loads the two local fixtures and reports `changes.greeting: Goodbye`.
The before fixture uses schema version 1, which ConfigKit reports as a provider
warning in verbose mode. Ordinary mode hides the warning while preserving the
effective YAML report; quiet mode suppresses that report.
The invalid fixture demonstrates a failed-load report and captured source
inventory; `source-1` is the ID from that fixture's acquisition. The scope opts
in to transient overrides and passes them into its normal ConfigKit load. The
diff example compares an overridden left side with ordinary configuration on
the right and returns status 3 because the values differ.
The handler reports its greeting, count, and tags. It distinguishes an omitted
count from an explicitly supplied zero and preserves repeated tag order.
## How it is wired
One ConfigKit scope supplies the standard `config` commands. Without `--config`,
its loader uses an in-memory default. Supplied configuration and overlay values
are passed to ConfigKit unchanged. The scope enables temporary overrides and
passes them into its ordinary ConfigKit load. The
[consumer guide](../../../../docs/consumers/guide.md#configkit-scopes) explains
loader and scope setup.
Run `GOWORK=off GOTOOLCHAIN=local go test ./...` from this example directory to
check it against its declared dependencies.

View File

@@ -73,13 +73,13 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
scopeChoices = append(scopeChoices, commandkit.CompletionChoice{Value: "all"})
}
flags := []commandkit.Flag[*configCommandInput[I, S]]{
commandkit.ValueFlag(commandkit.FlagMeta{Name: "scope", Usage: "Configuration scope name or all where supported.", Completion: commandkit.CompleteChoices(scopeChoices...)}, &defaultScope, parseConfigString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "scope", Usage: "Select a named configuration, or all where supported.", Completion: commandkit.CompleteChoices(scopeChoices...)}, &defaultScope, parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).scope = value }),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration source.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseConfigString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration source.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) {
(*input).selection.Config = value
}),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Overlay source.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseConfigString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) {
(*input).selection.Overlay = value
}),
@@ -89,11 +89,11 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
}
if operation == Validate {
flags = append(flags,
commandkit.BoolFlag(commandkit.FlagMeta{Name: "details", Usage: "Show native validation findings."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).details = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "details", Usage: "Show detailed validation findings."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).details = value }),
commandkit.RepeatFlag(commandkit.FlagMeta{Name: "severity", Usage: "Filter detailed findings by error or warning."}, []configkit.Severity(nil), parseValidationSeverity, func(input **configCommandInput[I, S], value commandkit.Supplied[[]configkit.Severity]) {
(*input).severities = value.Value
}),
commandkit.RepeatFlag(commandkit.FlagMeta{Name: "code", Usage: "Filter detailed findings by exact native code."}, []string(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[[]string]) {
commandkit.RepeatFlag(commandkit.FlagMeta{Name: "code", Usage: "Filter detailed findings by exact diagnostic code."}, []string(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[[]string]) {
(*input).codes = value.Value
}),
)
@@ -114,16 +114,16 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "path", Usage: "JSON Pointer path to explain."}, (*string)(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).path = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "list", Usage: "List configuration paths."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).list = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "historical", Usage: "Include historical-only paths when listing."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).historical = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "historical", Usage: "Include paths that exist only in configuration history."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).historical = value }),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "under", Usage: "List paths under a JSON Pointer."}, (*string)(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).under = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "explicit", Usage: "Filter listed current paths by explicitness."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).explicit = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "explicit", Usage: "Filter current paths by whether ConfigKit marks them explicit."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).explicit = value }),
)
}
if operation == Show {
flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "path", Usage: "JSON Pointer to one effective value."}, (*string)(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).path = value }))
}
if operation == Sources {
flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "source-id", Usage: "Select one source ID from this acquisition."}, (*string)(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).sourceID = value }))
flags = append(flags, commandkit.ValueFlag(commandkit.FlagMeta{Name: "source-id", Usage: "Show one source ID from this configuration load."}, (*string)(nil), parseConfigString, func(input **configCommandInput[I, S], value commandkit.Supplied[string]) { (*input).sourceID = value }))
}
flags = append(flags, commandkit.CaptureFlags(prepared.bindingsByOperation[operation], func(input **configCommandInput[I, S]) *commandkit.FlagValues[I] {
if input == nil || *input == nil {
@@ -160,7 +160,7 @@ func newConfigOperationCommand[I, S any](prepared *preparedSuite[I, S], operatio
func comparisonOperationFlags[I, S any]() []commandkit.Flag[*configCommandInput[I, S]] {
return []commandkit.Flag[*configCommandInput[I, S]]{
commandkit.BoolFlag(commandkit.FlagMeta{Name: "details", Usage: "Show native before and after difference evidence."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).details = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "details", Usage: "Show before and after values with presence and redaction details."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).details = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "check", Usage: "Return status 3 when differences are found."}, false, func(input **configCommandInput[I, S], value commandkit.Supplied[bool]) { (*input).check = value }),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "against-config", Usage: "Configuration source for the right side.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseConfigString,
func(input **configCommandInput[I, S], value commandkit.Supplied[string]) {
@@ -191,7 +191,7 @@ func operationDeclaration(operation Operation) (string, string) {
case Explain:
return "explain", "Explain a configuration path."
case Diff:
return "diff", "Compare two configuration selections."
return "diff", "Compare two configurations."
default:
return string(operation), "Inspect configuration."
}

View File

@@ -1,37 +1,40 @@
# CommandKit ckprompt
`ckprompt` is the optional PromptKit integration for CommandKit. It adapts
PromptKit engine configuration, native comparison, five catalogs, named
inspection, requirements discovery and validation, and native smoke tests.
Importing it does not install either command family.
`ckprompt` adds PromptKit inspection and testing commands to Go applications
that use CommandKit. Operators can list prompts, profiles, and backends, inspect
their settings, discover required inputs, validate and preview requests, and
run smoke tests.
The application chooses which commands to install. Importing the package alone
does not install commands.
## Module
The module path is `go.maximumdirect.net/ckprompt`. This source uses Go 1.27.0,
`go.maximumdirect.net/commandkit v0.4.0`, `go.maximumdirect.net/ckconfig v0.4.0`,
`go.maximumdirect.net/configkit v1.1.0`, and `go.maximumdirect.net/promptkit v0.20.0`. See the
[consumer guide](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/consumers/guide.md#promptkit-configuration-definitions-and-requirements)
for callback, input, state, and acquisition contracts.
The module path is `go.maximumdirect.net/ckprompt`. See the
[consumer guide](https://forge.maximumdirect.net/base-layer/commandkit/src/branch/main/docs/consumers/guide.md#module-selection)
for compatible releases, Go requirements, and the current source's dependency
alignment requirement.
## Example
Add `ckprompt.ConfigScope(loadEngine)` to the scopes passed to
`ckconfig.Command` when the application wants PromptKit engine configuration
and native comparison in the `config` family. Install
`ckprompt.Command(ckprompt.FromEngine(loadEngine))` separately for catalogs,
named inspections, and requirements discovery. `FromEngine` supplies nine
PromptKit-backed callbacks: four inspections and five catalogs. Applications
may narrow, wrap, or replace them before capture or provide custom callbacks
with `ckprompt.Suite`. Add concrete request validation, prepared-request preview,
and smoke testing explicitly with `WithRequestValidation`,
`WithRequestPreparation`, and `WithSmokeTesting`. Inspection,
requirements, and catalog operations do not execute prompts or contact model
providers; application loaders and callbacks retain their own effects. Smoke
testing invokes the selected native PromptKit operation; the
application retains ownership of client and configuration choices. See the
[CLI reference](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/cli.md#promptkit-smoke-testing)
for operator commands and report semantics. The maintained
[composed example](examples/composed) shows complete application wiring.
Pass your engine loader to `FromEngine` to add resource listings, inspection,
and requirements discovery:
```go
app, err := commandkit.New(identity, ckprompt.Command(ckprompt.FromEngine(loadEngine)))
```
Add request validation, preview, and smoke tests with `WithRequestValidation`,
`WithRequestPreparation`, and `WithSmokeTesting`. To expose engine configuration
under `config`, add `ckprompt.ConfigScope(loadEngine)` to a `ckconfig.Suite`.
The [integration guide](https://forge.maximumdirect.net/base-layer/commandkit/src/branch/main/docs/consumers/guide.md#promptkit-configuration-definitions-and-requirements)
explains these choices; the [composed example](examples/composed) shows them together.
Inspection commands do not call the model. Smoke tests can use the application's
configured client or network probes. Applications own engine setup, credentials,
and any effects of their loaders and callbacks. See the
[CLI reference](https://forge.maximumdirect.net/base-layer/commandkit/src/branch/main/docs/cli.md#promptkit-smoke-testing)
for commands and results.
## License and attribution

View File

@@ -91,7 +91,7 @@ func buildCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Declaration
showCommands = append(showCommands, newPreparationCommand(suite, aliases))
}
if len(showCommands) != 0 {
rootCommands = append(rootCommands, commandkit.Group("show", "Show a named PromptKit definition.", showCommands...))
rootCommands = append(rootCommands, commandkit.Group("show", "Show PromptKit definitions or preview a prepared request.", showCommands...))
}
listCommands := make([]commandkit.Command, 0, 5)
if suite.ListPrompts != nil {
@@ -110,7 +110,7 @@ func buildCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Declaration
listCommands = append(listCommands, newCatalogListCommand(suite, "collections"))
}
if len(listCommands) != 0 {
rootCommands = append(rootCommands, commandkit.Group("list", "List PromptKit catalogs.", listCommands...))
rootCommands = append(rootCommands, commandkit.Group("list", "List available PromptKit resources.", listCommands...))
}
requirementsCommands := make([]commandkit.Command, 0, 2)
if suite.InspectRequirements != nil {
@@ -125,7 +125,7 @@ func buildCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Declaration
if suite.SmokeTest != nil {
rootCommands = append(rootCommands, newSmokeTestCommand(suite, aliases))
}
command := commandkit.RootGroup("promptkit", "Inspect, list, validate requests, and run PromptKit smoke tests.", rootCommands...)
command := commandkit.RootGroup("promptkit", "Inspect PromptKit resources, check requests, and run smoke tests.", rootCommands...)
for _, issue := range suite.issues {
command = commandkit.WithError(command, issue)
}
@@ -140,16 +140,16 @@ func newCatalogListCommand[I, S any](suite Suite[I, S], name string) commandkit.
return &(*input).captured
})
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **catalogInput[I], value commandkit.Supplied[string]) { (*input).selection.Config = value }),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **catalogInput[I], value commandkit.Supplied[string]) { (*input).selection.Overlay = value }),
)
if name == "prompts" || name == "profiles" || name == "backends" {
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "namespace", Usage: "Select one native namespace."}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "namespace", Usage: "List resources in one namespace."}, (*string)(nil), parseDefinitionString,
func(input **catalogInput[I], value commandkit.Supplied[string]) { (*input).namespace = value }),
commandkit.BoolFlag(commandkit.FlagMeta{Name: "all-namespaces", Usage: "Select identities from every namespace."}, false,
commandkit.BoolFlag(commandkit.FlagMeta{Name: "all-namespaces", Usage: "List resources from every namespace."}, false,
func(input **catalogInput[I], value commandkit.Supplied[bool]) { (*input).allNamespaces = value }),
)
}
@@ -243,9 +243,9 @@ func newDefinitionCommand[I, S any](suite Suite[I, S], name string, aliases *[]c
return &(*input).captured
})
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **definitionInput[I], value commandkit.Supplied[string]) { (*input).selection.Config = value }),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **definitionInput[I], value commandkit.Supplied[string]) {
(*input).selection.Overlay = value
}),
@@ -288,11 +288,11 @@ func newRequirementsCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.D
return &(*input).captured
})
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
(*input).selection.Config = value
}),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **requirementsInput[I], value commandkit.Supplied[string]) {
(*input).selection.Overlay = value
}),
@@ -308,8 +308,8 @@ func newRequirementsCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.D
spec := commandkit.CommandSpec[*requirementsInput[I]]{
Name: "show",
Summary: "Inspect requirements for a named PromptKit prompt.",
Description: "Profile selection establishes the reported profile identity, not a different set of requirements. A profile namespace qualifies an explicitly supplied short profile ID, not the prompt’s stored default reference.",
Summary: "Discover the inputs and variables a prompt needs.",
Description: "List required inputs without running the prompt. Choosing a profile changes the reported profile ID, not the requirements. A profile namespace applies to a short profile ID supplied here; it does not change the prompt’s stored default reference.",
NewInput: func() *requirementsInput[I] {
return &requirementsInput[I]{}
},

View File

@@ -1,13 +1,13 @@
// Package ckprompt, provided by go.maximumdirect.net/ckprompt, provides optional
// PromptKit configuration comparison,
// prompt catalogs, named inspections, requirements discovery and validation,
// prepared-request preview, and native smoke testing for CommandKit. Command
// returns a canonical declaration; Declarations adds scoped flag aliases.
// Applications can install those alongside other declarations through
// commandkit.New or App.Register. Importing ckprompt installs neither family; callers compose its
// declarations with core and ckconfig explicitly. Provider diagnostics remain
// passive until the owning command submits them through the invocation
// reporter, separately from any terminal explanation. This module uses
// PromptKit v0.20.0 and its native engine inventory, including configured
// bundled resources.
// Package ckprompt adds PromptKit inspection and testing commands to CommandKit
// applications. Operators can list resources, inspect definitions, discover
// required inputs, validate and preview requests, and run smoke tests.
//
// Start with FromEngine and add optional operations with WithRequestValidation,
// WithRequestPreparation, and WithSmokeTesting. Command returns the command
// family; Declarations also includes its convenience flag aliases. Install
// these with commandkit.New or App.Register.
//
// ConfigScope separately exposes engine configuration through ckconfig.
// Importing this package installs neither command family. Applications own
// engine construction, credentials, and client configuration.
package ckprompt

View File

@@ -1,27 +1,40 @@
# CommandKit ckprompt v0.3.0
CommandKit ckprompt v0.3.0 adopts PromptKit v0.20.0 and ConfigKit v1.1.0,
and requires CommandKit core v0.4.0, ckconfig v0.4.0, and Go 1.27.0.
The integration uses shared core reporting for text, YAML, and JSON output.
This unpublished candidate adds PromptKit v0.20.0 support, including request
preview, namespace selection, and shared text, YAML, and JSON output. It uses
ConfigKit v1.1.0 and requires Go 1.27.0.
Prompt, profile, and backend commands report PromptKit's native resource
inspections. Applications may opt into prepared-request preview, concrete
request validation, smoke testing, and namespace selectors independently.
Reusable request flag collections support application-owned commands;
`ckprompt.Declarations` installs the standard family with scoped aliases.
Literal and file inputs retain their command-line order. Provider parameters
can be supplied for preparation and applicable diagnostics.
## Operator features
The PromptKit configuration scope exposes native metadata and load-failure
evidence through ckconfig, including independent comparison selections,
detailed differences, and validation findings. Smoke reports retain native
evidence and operation failures separately from presentation failures.
- Inspect prompts, profiles, and backends, and list available resources.
- Preview rendered requests without calling the model, or validate that a
request can be prepared with the supplied inputs.
- Choose namespaces and override request settings for supported commands.
- Run smoke tests and inspect their results, including incomplete or unsupported
checks and reports returned alongside errors.
- Inspect engine configuration through `config`, including detailed validation
findings, source information after failed loads, and configuration comparisons.
This pre-1.0 release changes resource report shapes, input flags, formatting,
and configuration comparison behavior. Applications should update declarations
and report consumers to the current [CLI reference](../../../../docs/cli.md#promptkit-definition-inspection)
and [consumer guide](../../../../docs/consumers/guide.md#promptkit-configuration-definitions-and-requirements).
Applications continue to own engine construction, credentials, and execution.
Applications choose which commands to enable. Reusable flag collections also
let application commands offer the same request flags. `ckprompt.Declarations`
adds the standard commands with their shorter flag aliases. Literal and file
inputs keep their command-line order.
## Compatibility and preparation
This candidate changes resource report shapes, input flags, formatting, and
configuration comparison behavior. Review the current
[CLI reference](../../../../docs/cli.md#promptkit-definition-inspection) and
[consumer guide](../../../../docs/consumers/guide.md#promptkit-configuration-definitions-and-requirements)
when updating declarations or code that reads reports. Applications continue to
own engine construction, credentials, and execution.
The current source requires `ckconfig.AdaptDiagnostics`, which is absent from
its selected ckconfig v0.4.0 dependency. Before publication, complete
[dependency alignment](../../../../docs/roadmap/future.md#pending-release-and-integration-work)
and update this candidate's dependency guidance to the selected releases.
The [module selection table](../../../../docs/consumers/guide.md#module-selection)
distinguishes published combinations from the current workspace.
[COPYRIGHT](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/integrations/ckprompt/v0.3.0/integrations/ckprompt/COPYRIGHT) |
[LICENSE](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/integrations/ckprompt/v0.3.0/integrations/ckprompt/LICENSE) |

View File

@@ -1,141 +1,172 @@
# Composed consumer
# ConfigKit and PromptKit example
This example is part of the ckprompt module and uses core v0.4.0, ckconfig
v0.4.0, ConfigKit v1.1.0, and PromptKit v0.20.0. It requires Go 1.27.0.
This example combines application and PromptKit configuration, resource
inspection, request checks, and smoke tests. It uses local fixtures and an
in-memory model client. **No model service or credentials are required.**
This example composes application configuration, PromptKit configuration,
PromptKit comparison and catalogs, definition and requirements inspection, and
one application-owned command:
Use Go 1.27.0 on `PATH` and an aligned workspace containing all three local
modules. Follow the [workspace setup](../../../../docs/development.md#documentation-validation)
from the repository root first. Current ckprompt source needs a helper in local
ckconfig source that its released dependency does not yet contain; independent
builds remain pending [release alignment](../../../../docs/roadmap/future.md#pending-release-and-integration-work).
The [consumer guide](../../../../docs/consumers/guide.md#module-selection) owns
version and compatibility details.
From the repository root:
```sh
cd integrations/ckprompt/examples/composed
export GOWORK=auto GOTOOLCHAIN=local
go run . config scopes
go run . promptkit list prompts --campaign spring
go run . promptkit show prompt briefing --campaign spring --format yaml
```
The first command lists `app` and `promptkit` configurations and their available
operations. The next commands find and inspect the `briefing` prompt.
`--campaign` is a selector supplied by this example, not a standard PromptKit flag.
## Validate and compare configuration
```sh
go run . config validate --scope all --campaign spring --limit=0
go run . config diff --scope app --config fixtures/before.yml --against-config fixtures/after.yml
go run . config diff --scope app --config fixtures/before.yml --against-config fixtures/after.yml --campaign spring --limit=0
go run . config diff --scope app --campaign spring --limit=0 --against-campaign autumn --against-limit=0 --set '/campaigns/spring/model="left"' --against-set '/campaigns/spring/model="right"' --details
go run . config diff --scope promptkit --config fixtures/before.yml --against-config fixtures/after.yml --campaign spring --against-campaign spring
go run . promptkit list prompts --config fixtures/before.yml --campaign spring
```
The application scope requires `--limit=0` when `--campaign` is supplied.
The app comparison reports a changed default campaign and `campaigns.spring.model`.
The PromptKit comparison selects spring on both sides and reports the changed
profiles list as one value.
The two sides have independent selectors and overrides:
```sh
go run . config diff --scope app --campaign spring --limit=0 --against-campaign autumn --against-limit=0 --set '/campaigns/spring/model="left"' --against-set '/campaigns/spring/model="right"' --details
```
Only the application scope supports `--set` here. The released PromptKit loader
has no override handoff, so its configuration scope does not enable the feature.
An aggregate operation that includes that scope rejects overrides.
## List resources and select namespaces
```sh
go run . promptkit list profiles --config fixtures/after.yml --campaign autumn --format yaml
go run . promptkit list backends --campaign spring
go run . promptkit list namespaces --campaign spring
go run . promptkit list collections --campaign spring
go run . list collections --campaign spring
go run . pk list bundles --campaign spring
go run . promptkit list prompts --namespace field-notes --campaign spring
go run . promptkit show prompt briefing --campaign spring --format yaml
go run . promptkit show prompt briefing --campaign spring --prompt-namespace field-notes
go run . promptkit show prepared briefing --campaign spring --input topic=sprint --profile spring --extra-params '{"campaign":"preview"}'
go run . pk show prompt briefing --campaign spring --fmt yaml
go run . promptkit show profile spring --campaign spring
```
The profile list includes the selected `autumn` profile. PromptKit's default
bundle contributes additional resources. The example also supplies a
`field-notes` collection containing a backend, profile, and prompt. Listing
filters and resource namespace flags let you inspect that collection.
## Discover inputs, then check a request
```sh
go run . promptkit requirements show briefing --campaign spring
go run . promptkit requirements show briefing --campaign spring --var mode=full --format yaml
```
The first report is incomplete: the `notes` input is conditional and `mode` is
missing. Supplying `mode=full` selects that branch and makes `notes` required.
Both commands succeed; discovery alone does not establish that a request can run.
```sh
go run . promptkit requirements validate briefing --campaign spring --llm-input-file topic=fixtures/topic.txt
go run . promptkit requirements validate briefing --campaign spring --llm-input-file topic=fixtures/topic.txt --llm-var mode=full --llm-input-file notes=fixtures/notes.txt --format yaml
```
Both commands check request preparation and report `prompt_id` and `valid: true`.
The builder provides campaign-specific variable defaults; the operator supplies
the input files. For comparison, this command intentionally fails because the
required `topic` input is missing:
```sh
# Intentional failure: missing topic input.
go run . promptkit requirements validate briefing --campaign spring
```
Preview a request with literal input instead of a file:
```sh
go run . promptkit show prepared briefing --campaign spring --input topic=sprint --profile spring --extra-params '{"campaign":"preview"}'
```
The preview includes rendered messages and effective provider settings.
Validation and preview do not call the model or guarantee later execution.
## Run smoke tests
```sh
go run . promptkit test text_inference --campaign spring --prompt briefing --profile spring
go run . smoke text_inference --campaign spring --llm-prompt briefing --llm-profile spring
# Some diagnostics can fail or be unsupported; inspect the retained report.
go run . promptkit test all --campaign spring --llm-prompt briefing --llm-profile spring
```
Inference uses the example's in-memory client. HTTP checks may be unsupported
or not applicable because the local backend has no network probe. The aggregate
can return a failure while still showing results. Read the facts in the report;
a successful command status does not mean every observation is positive.
For any command that returns nonzero, `go run` prints `exit status N` and itself
exits with status 1. A built executable returns the application's status directly.
The [CLI reference](../../../../docs/cli.md#promptkit-smoke-testing) explains the
standard test kinds, results, and statuses.
## Try aliases and application commands
```sh
go run . list collections --campaign spring
go run . pk list bundles --campaign spring
go run . pk show prompt briefing --campaign spring --fmt yaml
go run . smoke text_inference --campaign spring --llm-prompt briefing --llm-profile spring
go run . pk --hlep
go run . session restore session-42 --campaign spring
go run . request inspect --llm-prompt briefing --llm-profile= --llm-model example --llm-input-text topic=sprint --format json
```
`newApp` installs application-owned command and flag aliases alongside the
complete `ckconfig` and `ckprompt` declarations. `list collections` and
`promptkit list bundles` both reach the canonical collection command; `pk`
shortens the PromptKit group. `--fmt` is scoped to named prompt inspection and
`--hlep` is available globally. The `smoke` shortcut retains the canonical
`promptkit test KIND` operand, including the special `all` aggregate.
The first two commands reach `promptkit list collections`. `pk` shortens the
PromptKit group; `--fmt` is an alias on prompt inspection and `--hlep` is a global
help alias. `smoke` shortens `promptkit test` while leaving the test kind as an
argument. The session command uses an in-memory store. `request inspect` shows
how an application command can reuse canonical `--llm-*` flag collections without
installing PromptKit's short aliases.
The example installs `Completion("composed-example")`. Build it as
`go build -o composed-example .`. Initialize `bash-completion` first if using
Bash, then load a shell script as described in the
[CLI reference](../../../../docs/cli.md#shell-completion). Try completion after
`composed-example pk show prompt briefing --fmt=` or after the filename prefix
in `composed-example config show --config=fixtures/`. The already-entered `pk`
alias selects the PromptKit command context without loading an engine.
## Try shell completion
The composition installs `ckconfig.Command(suite)` and the complete
`ckprompt.Declarations(definitions)` in a `[]commandkit.Declaration` with
root-installed routing rules. The PromptKit declarations include scoped aliases;
the application-owned `request inspect` command reuses the flag collections
with their canonical names and does not install those aliases.
Group children remain canonical `Command` values. For command-only slices,
convert each `Command` to `Declaration` before appending aliases. The
[consumer guide](../../../../docs/consumers/guide.md#application-owned-aliases)
includes minimal direct-call and slice-conversion examples; this README documents
the maintained complete consumer.
The sources and session store are small in-memory fixtures. `--campaign` is a
typed selector shared by the app and PromptKit configuration scopes. Their
`ckconfig.Suite[*inspectionInput, *runCache]` uses `NewInput` to initialize each
selected scope's input separately and `NewState` to create one cache shared by
that invocation's acquisitions. Prompt/profile inspection prepares its input and
cache independently for its invocation, using the same application and engine
loader functions. See the
[consumer guide](https://gitea.maximumdirect.net/eric/CommandKit/src/branch/main/docs/consumers/guide.md)
and the suites' GoDoc for initialization timing and ownership.
The application-scope comparison reports the changed default campaign and the
updated `campaigns.spring.model`. The PromptKit-scope comparison selects spring
on both sides and reports the native engine change in the atomic profiles list.
The application input check requires `--limit=0` when `--campaign` is supplied.
Catalogs use the same selection-aware loader: the prompt catalog includes
`briefing`, and the profile catalog includes the selected `autumn` profile.
Prompt inspection uses an ID only. The default PromptKit bundle also contributes
profiles and a backend to the engine inventory and source reports. The synthetic `field-notes` collection
provides one backend, profile, and prompt for collection discovery and native
namespace filtering. The example's shared run cache keys successful results by
the complete supplied configuration/overlay selection, CLI overrides, and the
supplied campaign, including presence. The campaign override and application
scope's `--set` records are applied through ConfigKit before loading. The
PromptKit configuration scope does not enable `--set` because its released
configuration loader has no override handoff. An aggregate operation therefore
rejects overrides when that scope is selected. These are choices for this
example's loaders and do not define a CommandKit cache policy.
Smoke testing is explicitly wired with `ckprompt.WithSmokeTesting` and its
optional request builder is nil, so CommandKit forwards the selected native
request. Applications that need to adjust the request can provide a typed
builder that starts with the seed and returns the chosen native request:
```go
definitions = ckprompt.WithSmokeTesting(definitions, loadEngine,
func(ctx context.Context, seed ckprompt.SmokeRequest, input *inspectionInput, state *runCache) (promptkit.SmokeTestRequest, error) {
request := seed.Request
request.ProfileID = "spring"
return request, nil
})
```sh
go build -o composed-example .
./composed-example completion bash
```
The example injects a small in-memory `promptkit.LLMClient` through its shared
run state. Catalog, inspection, and requirements commands do not call it;
inference smoke commands do. No model service or credentials are required.
Native HTTP checks may retain unsupported or not-applicable observations because
the selected local backend does not configure a network probe. An aggregate smoke command can
return an operational outcome for a native diagnostic while still delivering
the complete aggregate report.
Initialize `bash-completion` if using Bash, then load the generated script using
the [CLI reference](../../../../docs/cli.md#shell-completion). Try completing
`composed-example pk show prompt briefing --fmt=` or
`composed-example config show --config=fixtures/`. The already-entered `pk` alias
selects the command context without loading an engine.
The first requirements command reports incomplete discovery: PromptKit records
the conditional `notes` input and a missing `mode` issue. Supplying `mode=full`
selects that branch, classifies the undeclared `notes` input as required, and
completes discovery. Both commands return successful reports; the result does
not execute the prompt or establish input, credential, or execution readiness.
See the [CLI reference](../../../../docs/cli.md#promptkit-requirements) for the
command and report contract.
## How it is wired
The validation and preview commands exercise concrete PromptKit request preparation.
The first uses the builder's campaign-specific default topic variable and the
operator's topic file. The second also selects the notes branch and supplies its
file. Validation reports only `prompt_id` and `valid: true`; preview returns the
prepared request, including rendered messages and effective provider settings.
Neither executes the prompt. The validation command without inputs intentionally
fails because the prompt's
required `topic` artifact is not supplied. The builder defaults variables from
the selected campaign but leaves artifact bindings to the operator. The
`requirements show` commands remain discovery reports: partial discovery can
succeed even when a concrete request would fail validation.
The example installs `ckconfig.Command(suite)` and
`ckprompt.Declarations(definitions)` with application-owned aliases in a
`[]commandkit.Declaration`. `NewInput` initializes scope inputs; `NewState`
creates a cache shared within an invocation. The loaders cache successful
configuration results by the complete configuration/overlay selection,
overrides, and supplied campaign, including whether each value was supplied.
These are example choices, not a CommandKit cache policy.
Run `GOWORK=off go test ./...` from this example directory to check it against
its declared dependencies. The [developer guide](../../../../docs/development.md#documentation-validation)
also describes aligned workspace tests.
Smoke testing uses `WithSmokeTesting` with a nil builder, forwarding the request
selected by flags. Applications can supply a builder to customize that request.
See the [consumer guide](../../../../docs/consumers/guide.md#promptkit-configuration-definitions-and-requirements)
for suite composition, builders, and ownership, and the [source](main.go) for
the complete application.
Run `GOWORK=auto GOTOOLCHAIN=local go test ./...` from this example directory
for an aligned workspace check. Once dependency alignment is complete, also use
`GOWORK=off GOTOOLCHAIN=local go test ./...` to check the declared releases.

View File

@@ -39,9 +39,9 @@ func namespaceFlags[I any](destination func(*I) *namespaceInput, kinds ...string
}
var namespaceFlagDefinitions = struct{ prompt, profile, backend requestFlagDefinition }{
prompt: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-prompt-namespace", Usage: "Prompt resource namespace."}, []string{"prompt-namespace"}},
profile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-profile-namespace", Usage: "Profile resource namespace."}, []string{"profile-namespace"}},
backend: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-backend-namespace", Usage: "Backend resource namespace."}, []string{"backend-namespace"}},
prompt: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-prompt-namespace", Usage: "Use this namespace for unqualified prompt IDs."}, []string{"prompt-namespace"}},
profile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-profile-namespace", Usage: "Use this namespace for unqualified profile IDs."}, []string{"profile-namespace"}},
backend: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-backend-namespace", Usage: "Use this namespace for unqualified backend IDs."}, []string{"backend-namespace"}},
}
func selectedNamespaces(defaults *promptkit.Namespaces, selected namespaceInput) *promptkit.Namespaces {

View File

@@ -35,24 +35,24 @@ var requestFlags = struct {
InputText requestFlagDefinition
InputFile requestFlagDefinition
}{
Endpoint: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-endpoint", Usage: "Execution endpoint override."}, []string{"endpoint"}},
Model: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-model", Usage: "Execution model override."}, []string{"model"}},
Temperature: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-temperature", Usage: "Execution temperature override."}, []string{"temperature"}},
MaxTokens: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-max-tokens", Usage: "Execution maximum tokens override."}, []string{"max-tokens"}},
TopP: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-top-p", Usage: "Execution top-p override."}, []string{"top-p"}},
TimeoutSeconds: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-timeout-seconds", Usage: "Execution timeout override in seconds."}, []string{"timeout-seconds"}},
ServiceTier: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-service-tier", Usage: "Execution service tier."}, []string{"service-tier"}},
ReasoningEffort: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-reasoning-effort", Usage: "Execution reasoning effort override."}, []string{"reasoning-effort"}},
APIKeyEnv: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-api-key-env", Usage: "Execution API key environment variable."}, []string{"api-key-env"}},
TransientRetries: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-transient-retries", Usage: "Inference transient retry count."}, []string{"transient-retries"}},
ExtraParams: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-extra-params", Usage: "Execution provider parameters as a JSON object."}, []string{"extra-params"}},
Prompt: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-prompt", Usage: "PromptKit prompt ID."}, []string{"prompt"}},
Profile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-profile", Usage: "PromptKit profile ID."}, []string{"profile"}},
Backend: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-backend", Usage: "PromptKit backend ID."}, []string{"backend"}},
SessionID: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-session-id", Usage: "PromptKit session ID."}, []string{"session-id"}},
Var: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-var", Usage: "Caller variable assignment KEY=VALUE."}, []string{"var"}},
InputText: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-text", Usage: "Literal prompt input assignment NAME=TEXT."}, []string{"input-text", "llm-input", "input"}},
InputFile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-file", Usage: "Prompt input file assignment NAME=PATH."}, []string{"input-file"}},
Endpoint: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-endpoint", Usage: "Use this endpoint."}, []string{"endpoint"}},
Model: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-model", Usage: "Use this model."}, []string{"model"}},
Temperature: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-temperature", Usage: "Use this temperature."}, []string{"temperature"}},
MaxTokens: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-max-tokens", Usage: "Use this maximum token count."}, []string{"max-tokens"}},
TopP: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-top-p", Usage: "Use this top-p value."}, []string{"top-p"}},
TimeoutSeconds: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-timeout-seconds", Usage: "Set the request timeout in seconds."}, []string{"timeout-seconds"}},
ServiceTier: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-service-tier", Usage: "Use this service tier."}, []string{"service-tier"}},
ReasoningEffort: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-reasoning-effort", Usage: "Use this reasoning effort."}, []string{"reasoning-effort"}},
APIKeyEnv: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-api-key-env", Usage: "Name the environment variable containing the API key."}, []string{"api-key-env"}},
TransientRetries: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-transient-retries", Usage: "Set the retry count for transient inference failures."}, []string{"transient-retries"}},
ExtraParams: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-extra-params", Usage: "Supply provider parameters as a JSON object."}, []string{"extra-params"}},
Prompt: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-prompt", Usage: "Select a prompt by ID."}, []string{"prompt"}},
Profile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-profile", Usage: "Select a profile by ID."}, []string{"profile"}},
Backend: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-backend", Usage: "Select a backend by ID."}, []string{"backend"}},
SessionID: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-session-id", Usage: "Supply the session ID."}, []string{"session-id"}},
Var: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-var", Usage: "Supply a prompt variable as KEY=VALUE."}, []string{"var"}},
InputText: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-text", Usage: "Supply text for a prompt input as NAME=TEXT."}, []string{"input-text", "llm-input", "input"}},
InputFile: requestFlagDefinition{commandkit.FlagMeta{Name: "llm-input-file", Usage: "Supply a file for a prompt input as NAME=PATH."}, []string{"input-file"}},
}
// ExecutionInput contains request-scoped execution controls supplied on the CLI.

View File

@@ -29,11 +29,11 @@ func newSmokeTestCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Decl
return &(*input).captured
})
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **smokeCommandInput[I], value commandkit.Supplied[string]) {
(*input).selection.Config = value
}),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **smokeCommandInput[I], value commandkit.Supplied[string]) {
(*input).selection.Overlay = value
}),
@@ -53,14 +53,15 @@ func newSmokeTestCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Decl
}
return commandkit.NewCommand(commandkit.CommandSpec[*smokeCommandInput[I]]{
Name: "test",
Summary: "Run one PromptKit smoke test.",
Name: "test",
Summary: "Run one or all PromptKit smoke tests.",
Description: "Tests use the configured client or probes and may contact a provider. The all option runs the four tests in order. Read the report: a successful command status does not mean every observation is positive.",
NewInput: func() *smokeCommandInput[I] {
return &smokeCommandInput[I]{}
},
Flags: flags,
Arguments: []commandkit.Argument[*smokeCommandInput[I]]{
commandkit.ValueArgument(commandkit.ArgumentMeta{Name: "kind", Usage: "Native smoke-test kind.", Completion: smokeKindCompletion()}, true, parseDefinitionString,
commandkit.ValueArgument(commandkit.ArgumentMeta{Name: "kind", Usage: "Test kind: reachability, authentication, text_inference, structured_output, or all.", Completion: smokeKindCompletion()}, true, parseDefinitionString,
func(input **smokeCommandInput[I], value commandkit.Supplied[string]) { (*input).kind = value.Value }),
},
CheckInput: func(input *smokeCommandInput[I]) error {

View File

@@ -31,11 +31,11 @@ func newConcreteRequestSpec[I, S any](suite Suite[I, S], path string, aliases *[
return &(*input).captured
})
flags = append(flags,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "config", Usage: "Select the configuration input path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **concreteRequestInput[I], value commandkit.Supplied[string]) {
(*input).request.Selection.Config = value
}),
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
commandkit.ValueFlag(commandkit.FlagMeta{Name: "overlay", Usage: "Select the configuration overlay path.", Completion: commandkit.CompleteFiles()}, (*string)(nil), parseDefinitionString,
func(input **concreteRequestInput[I], value commandkit.Supplied[string]) {
(*input).request.Selection.Overlay = value
}),
@@ -93,7 +93,7 @@ func newConcreteRequestSpec[I, S any](suite Suite[I, S], path string, aliases *[
func newValidationCommand[I, S any](suite Suite[I, S], aliases *[]commandkit.Declaration) commandkit.Command {
spec := newConcreteRequestSpec(suite, "promptkit requirements validate", aliases)
spec.Name = "validate"
spec.Summary = "Validate a concrete PromptKit request without executing it."
spec.Summary = "Check whether a request can be prepared without calling the model."
spec.Run = func(invocation commandkit.Invocation, input *concreteRequestInput[I]) commandkit.Outcome {
return runRequestValidation(invocation, suite, input)
}

View File

@@ -70,7 +70,7 @@ type CompletionResult struct {
}
var reportingFlags = [...]Flag{
{Name: "quiet", Usage: "suppress substantive output and optional messages; keep failures visible", Default: "false", Boolean: true},
{Name: "quiet", Usage: "hide command output and optional messages; keep failures visible", Default: "false", Boolean: true},
{Name: "verbose", Usage: "show warning and informational messages", Default: "false", Boolean: true},
{Name: "debug", Usage: "show debugging messages", Default: "false", Boolean: true},
{Name: "progress", Usage: "show progress messages", Default: "false", Boolean: true},