Document shared debug input and reporting mode

This commit is contained in:
2026-11-08 15:10:00 +00:00
parent d914295ced
commit 96c96bb793
8 changed files with 79 additions and 3 deletions

View File

@@ -84,6 +84,12 @@ func RenameFlag[I any](flag Flag[I], name string) Flag[I] {
// BoolFlag declares a boolean flag. A bare flag is supplied by the parser as // BoolFlag declares a boolean flag. A bare flag is supplied by the parser as
// "true"; explicit values are converted with strconv.ParseBool. Set distinguishes // "true"; explicit values are converted with strconv.ParseBool. Set distinguishes
// an omitted flag from an explicit false value. // an omitted flag from an explicit false value.
//
// A BoolFlag named debug receives the shared reporting flag's input. Its
// default and requiredness apply to application input, not reporting mode;
// explicit false satisfies requiredness. Its optional short spelling and
// completion metadata follow ordinary flag rules. The final input value can
// differ from [Invocation.ReportingMode] when other mode flags are supplied.
func BoolFlag[I any](meta FlagMeta, defaultValue bool, set func(*I, Supplied[bool])) Flag[I] { func BoolFlag[I any](meta FlagMeta, defaultValue bool, set func(*I, Supplied[bool])) Flag[I] {
binding := flagBinding[I]{identity: newBindingIdentity(), meta: meta, defaultText: fmt.Sprint(defaultValue), boolean: true} binding := flagBinding[I]{identity: newBindingIdentity(), meta: meta, defaultText: fmt.Sprint(defaultValue), boolean: true}
if set == nil { if set == nil {

View File

@@ -95,7 +95,8 @@ type FlagMeta struct {
// Name is a nonempty long name without leading dashes. It consists of // Name is a nonempty long name without leading dashes. It consists of
// Unicode lowercase letters or digits in segments separated by single // Unicode lowercase letters or digits in segments separated by single
// hyphens; digit-leading and numeric-only names are valid. The names help, // hyphens; digit-leading and numeric-only names are valid. The names help,
// quiet, verbose, debug, progress and format are reserved. // quiet, verbose, debug, progress and format are reserved, except that a
// BoolFlag named debug attaches to the shared reporting flag.
Name string Name string
// Short is an optional one-byte spelling other than '-' or the reserved 'h'. // Short is an optional one-byte spelling other than '-' or the reserved 'h'.
Short string Short string

View File

@@ -178,8 +178,11 @@ Reporting flags do not go before or between command-path components. Tokens
consumed as values and tokens after `--` retain their normal meaning. consumed as values and tokens after `--` retain their normal meaning.
The reserved long spellings are `--quiet`, `--verbose`, `--debug`, The reserved long spellings are `--quiet`, `--verbose`, `--debug`,
`--progress`, and `--format`; application declarations cannot reuse them. There `--progress`, and `--format`. An application may attach its own boolean input
are no built-in short spellings. Applications may define aliases such as `-q → --quiet`, to the existing `--debug` option. Command help shows both purposes in one row,
including an application short spelling, requiredness, and any different
application default. Application input defaults do not select reporting mode.
There are no built-in short spellings. Applications may define aliases such as `-q → --quiet`,
`-v → --verbose`, and `-d → --debug`; canonical and aliased occurrences share `-v → --verbose`, and `-d → --debug`; canonical and aliased occurrences share
the same ordering. Thus `example export --verbose -q` selects quiet mode. the same ordering. Thus `example export --verbose -q` selects quiet mode.

View File

@@ -154,6 +154,35 @@ Deferred submissions are accepted until finalization begins; later submissions
return `ErrReporterClosed`. The [CLI reference](../cli.md#reporting) owns flag return `ErrReporterClosed`. The [CLI reference](../cli.md#reporting) owns flag
grammar, visibility, prefixes, and status behavior. grammar, visibility, prefixes, and status behavior.
An application can attach a boolean input to the shared `--debug` option and
inspect the reporting selection separately. For example:
```go
type input struct { debug commandkit.Supplied[bool] }
command := commandkit.NewCommand(commandkit.CommandSpec[input]{
Name: "run",
Flags: []commandkit.Flag[input]{
commandkit.BoolFlag(commandkit.FlagMeta{Name: "debug", Short: "d"}, false,
func(in *input, value commandkit.Supplied[bool]) { in.debug = value }),
},
Run: func(inv commandkit.Invocation, in input) commandkit.Outcome {
captureArtifacts := in.debug.Value
quiet := inv.ReportingMode() == commandkit.ReportingModeQuiet
_, _ = captureArtifacts, quiet // Apply application policy here.
return commandkit.Success()
},
})
_ = command
```
With `run --debug --quiet`, the input is true and explicitly supplied, while
the selected reporting mode is quiet. Application defaults and requiredness
affect input, not mode selection; explicit false counts as supplied. Captured
bindings retain the usual selection and application behavior. Applications own
any artifact creation and other effects. The mode reports selection rather than
successful delivery; see [Invocation.ReportingMode](../../identity.go).
Reports use JSON serialization to establish the common value representation Reports use JSON serialization to establish the common value representation
for YAML and JSON. A text template receives the original value; without one, for YAML and JSON. A text template receives the original value; without one,
text uses readable scalar or string-list output and YAML for structured values. text uses readable scalar or string-list output and YAML for structured values.

View File

@@ -38,6 +38,12 @@ collected parser events through that selection. The selected mode therefore
applies to command execution, help, and version; routing and parsing failures applies to command execution, help, and version; routing and parsing failures
remain visible in every mode. remain visible in every mode.
An effective flag view combines a shared application debug binding with the
core declaration for parsing, help, and completion, while preserving the
application binding's position. The same occurrence stream selects reporting
mode independently of the prepared application value. The invocation's mode
accessor reads the reporter's selection under its existing state mutex.
The reporter owns invocation-scoped visibility, message formatting, managed The reporter owns invocation-scoped visibility, message formatting, managed
report rendering, delivery observations, and finalization. It presents queued report rendering, delivery observations, and finalization. It presents queued
messages after the handler returns, then a failed outcome's explanation, and messages after the handler returns, then a failed outcome's explanation, and

25
docs/releases/v0.6.0.md Normal file
View File

@@ -0,0 +1,25 @@
# CommandKit v0.6.0
CommandKit v0.6.0 lets applications bind the shared debug option to typed
input and inspect the selected reporting mode during and after an invocation.
## Changes
- A `BoolFlag` named `debug` attaches to the existing reporting option. Its
application default, requiredness, short spelling, and completion hints are
retained; help describes the combined option.
- `Invocation.ReportingMode` returns the resolved visibility selection, which
can differ from the bound debug value when other mode flags are supplied.
## Compatibility and upgrade
Other reporting flag names remain reserved. Applications choosing a required
debug binding require an explicit value; an explicit false satisfies it. A
true application default does not enable debug reporting. See the
[consumer guide](../consumers/guide.md#invocation-reporting) and
[CLI reference](../cli.md#reporting). The core consumer minimum remains Go
1.26.0 and the maintainer release toolchain remains Go 1.27.0.
[COPYRIGHT](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/v0.6.0/COPYRIGHT) |
[LICENSE](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/v0.6.0/LICENSE) |
[ATTRIBUTION](https://forge.maximumdirect.net/base-layer/commandkit/src/tag/v0.6.0/docs/oss/attribution.md)

View File

@@ -259,6 +259,10 @@ clearly distinguish application defaults from reporting selection.
## Stage 6 — Document the implemented contracts ## Stage 6 — Document the implemented contracts
**Complete.** GoDoc, the CLI reference, consumer and internal guidance describe
the shared binding and reporting selection. The core v0.6.0 candidate note
records the feature and compatibility impact; no release has been published.
1. Update `BoolFlag`, `FlagMeta`, binding composition, and Invocation GoDoc with 1. Update `BoolFlag`, `FlagMeta`, binding composition, and Invocation GoDoc with
the supported debug exception and mode API. Explain defaults, presence, the supported debug exception and mode API. Explain defaults, presence,
requiredness, short spellings, and retained mode without making all reporting requiredness, short spellings, and retained mode without making all reporting

View File

@@ -24,6 +24,8 @@ type FlagValues[I any] struct {
// each adapted flag stores its prepared value in target, associated with the // each adapted flag stores its prepared value in target, associated with the
// original inner binding identity. Copies of an original handle remain // original inner binding identity. Copies of an original handle remain
// selectable; an independently constructed lookalike does not. // selectable; an independently constructed lookalike does not.
// A captured debug BoolFlag shares reporting input as described by [BoolFlag];
// its requiredness is checked when selected for application.
func CaptureFlags[Outer, I any](flags []Flag[I], target func(*Outer) *FlagValues[I]) []Flag[Outer] { func CaptureFlags[Outer, I any](flags []Flag[I], target func(*Outer) *FlagValues[I]) []Flag[Outer] {
captured := make([]Flag[Outer], len(flags)) captured := make([]Flag[Outer], len(flags))
for index, original := range flags { for index, original := range flags {