From 96c96bb7933708b91dd621294807e4b58245ba10 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sun, 8 Nov 2026 15:10:00 +0000 Subject: [PATCH] Document shared debug input and reporting mode --- binding.go | 6 ++++++ command.go | 3 ++- docs/cli.md | 7 +++++-- docs/consumers/guide.md | 29 +++++++++++++++++++++++++++++ docs/internal/overview.md | 6 ++++++ docs/releases/v0.6.0.md | 25 +++++++++++++++++++++++++ docs/roadmap/implementation.md | 4 ++++ flag_values.go | 2 ++ 8 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 docs/releases/v0.6.0.md diff --git a/binding.go b/binding.go index 98be328..68a85e7 100644 --- a/binding.go +++ b/binding.go @@ -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 // "true"; explicit values are converted with strconv.ParseBool. Set distinguishes // 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] { binding := flagBinding[I]{identity: newBindingIdentity(), meta: meta, defaultText: fmt.Sprint(defaultValue), boolean: true} if set == nil { diff --git a/command.go b/command.go index eb82911..0206813 100644 --- a/command.go +++ b/command.go @@ -95,7 +95,8 @@ type FlagMeta struct { // Name is a nonempty long name without leading dashes. It consists of // Unicode lowercase letters or digits in segments separated by single // 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 // Short is an optional one-byte spelling other than '-' or the reserved 'h'. Short string diff --git a/docs/cli.md b/docs/cli.md index fe5d8ed..7d556be 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -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. The reserved long spellings are `--quiet`, `--verbose`, `--debug`, -`--progress`, and `--format`; application declarations cannot reuse them. There -are no built-in short spellings. Applications may define aliases such as `-q → --quiet`, +`--progress`, and `--format`. An application may attach its own boolean input +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 the same ordering. Thus `example export --verbose -q` selects quiet mode. diff --git a/docs/consumers/guide.md b/docs/consumers/guide.md index 33aaba2..f831755 100644 --- a/docs/consumers/guide.md +++ b/docs/consumers/guide.md @@ -154,6 +154,35 @@ 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. +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 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. diff --git a/docs/internal/overview.md b/docs/internal/overview.md index b93a366..dfc31ec 100644 --- a/docs/internal/overview.md +++ b/docs/internal/overview.md @@ -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 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 report rendering, delivery observations, and finalization. It presents queued messages after the handler returns, then a failed outcome's explanation, and diff --git a/docs/releases/v0.6.0.md b/docs/releases/v0.6.0.md new file mode 100644 index 0000000..251c3cd --- /dev/null +++ b/docs/releases/v0.6.0.md @@ -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) diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 7021cfc..4bccaae 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -259,6 +259,10 @@ clearly distinguish application defaults from reporting selection. ## 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 the supported debug exception and mode API. Explain defaults, presence, requiredness, short spellings, and retained mode without making all reporting diff --git a/flag_values.go b/flag_values.go index d9ca1b3..a7b86f8 100644 --- a/flag_values.go +++ b/flag_values.go @@ -24,6 +24,8 @@ type FlagValues[I any] struct { // each adapted flag stores its prepared value in target, associated with the // original inner binding identity. Copies of an original handle remain // 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] { captured := make([]Flag[Outer], len(flags)) for index, original := range flags {