227 lines
14 KiB
Markdown
227 lines
14 KiB
Markdown
# Shared debug binding and reporting-mode access
|
|
|
|
Status: agreed scope and public behavior; not implemented. OD-1 and OD-2 are
|
|
resolved; no significant open decisions remain.
|
|
Baseline: `69257066e21c12ea3492237ebee072598adea60c`.
|
|
|
|
## Purpose and authority
|
|
|
|
Applications should be able to receive the boolean value of CommandKit's
|
|
`--debug` flag through normal typed input binding. Applications that need the
|
|
resolved reporting mode should also have a read-only invocation API.
|
|
|
|
The [Audita request](audita-feature-request.md) motivated this work. Subsequent
|
|
discussion selected a broader distinction: application debug behavior and CLI
|
|
reporting visibility are separate choices. Audita's original requirement that
|
|
capture follow reporting mode is an application policy, not a CommandKit
|
|
requirement. This roadmap records the agreed direction from that discussion;
|
|
it does not treat every proposal in the original request as accepted.
|
|
|
|
The [architecture policy](../policy/architecture.md#ownership-boundaries) and
|
|
[ADR 0006](../adr/0006-invocation-reporting.md) already assign CLI mechanics to
|
|
core and domain behavior to applications. This work fits those boundaries and
|
|
does not require another ADR. Implemented behavior remains documented in
|
|
[Go declarations](../../command.go) and the [CLI reference](../cli.md#reporting)
|
|
until this work lands.
|
|
|
|
## Current baseline
|
|
|
|
| Area | Current implementation | Work needed |
|
|
| --- | --- | --- |
|
|
| Typed binding | `BoolFlag` in [binding.go](../../binding.go) converts supplied occurrences and applies the last boolean with `Supplied[bool]` presence. | Let a binding receive the existing core debug flag's input. |
|
|
| Registration | `FlagMeta` and `validateBindings` in [command.go](../../command.go) reserve every reporting name, including `debug`. | Recognize the selected shared-binding form without treating it as an independent competing flag. |
|
|
| Parser metadata | [commandmeta](../../internal/commandmeta/metadata.go) separates `CoreFlags` from consumer-indexed `Flags`; [parser.go](../../parser.go) supplies core flags to each command. | Preserve consumer binding identity and indexes while sharing one parser declaration. |
|
|
| Backend | [internal/cobra/parse.go](../../internal/cobra/parse.go) registers both lists, records occurrences, and extracts indexed values only for consumer flags. | Supply shared debug values and spellings to the participating binding without duplicate backend registration. |
|
|
| Reporting | `reduceReportingOccurrences` in [parser.go](../../parser.go) resolves the mutually exclusive mode from ordered occurrences. | Preserve that reduction independently of the bound debug boolean. |
|
|
| Invocation | [execute.go](../../execute.go) applies reporting selection before input preparation and execution. [reporter.go](../../reporter.go) stores the mode privately; [Invocation](../../identity.go) exposes no mode query. | Expose the already resolved selection through a CommandKit-owned public type. |
|
|
|
|
Simply permitting the name in registration is insufficient: the backend would
|
|
otherwise receive two declarations for `debug`. Existing occurrence capture is
|
|
the starting point; applications should not scan or reparse arguments.
|
|
|
|
## Targeted end state
|
|
|
|
### Bind the debug boolean independently
|
|
|
|
OD-1 is resolved: an application declares a normal `BoolFlag` with
|
|
`FlagMeta.Name` set to `debug`. CommandKit attaches that binding to the existing
|
|
core flag. The application uses the same `Flag[I]`, `Supplied[bool]`, command
|
|
binding list, and typed setter model as for other boolean flags. No dedicated
|
|
`DebugFlag` constructor is planned. Application metadata follows the accepted
|
|
OD-2 decision below.
|
|
Commands without such a binding retain the standard core flag and reporting
|
|
behavior.
|
|
|
|
This choice keeps the application API familiar and avoids another public
|
|
constructor. Core handles shared registration internally; an arbitrary
|
|
string-valued or custom-parser flag named `debug` is not equivalent to the
|
|
selected boolean binding merely because its name matches.
|
|
|
|
The shared binding receives `Supplied[bool]`: omission produces the application's
|
|
declared default with `Set=false`; an explicitly supplied false produces
|
|
`Value=false, Set=true`. Repeated debug occurrences follow ordinary boolean
|
|
binding semantics: every supplied value must be valid, and the last value wins.
|
|
Other reporting flags do not rewrite the bound debug value.
|
|
|
|
The following examples appear after a complete command path. They show the
|
|
ordinary false-default binding and the existing mode-selection rules together:
|
|
|
|
| Arguments | Debug value | Supplied | Resolved reporting mode |
|
|
| --- | --- | --- | --- |
|
|
| None | false | false | Ordinary |
|
|
| `--debug` | true | true | Debug |
|
|
| `--debug --quiet` | true | true | Quiet |
|
|
| `--quiet --debug` | true | true | Debug |
|
|
| `--debug --verbose` | true | true | Verbose |
|
|
| `--debug --debug=false` | false | true | Ordinary |
|
|
| `--verbose --debug --debug=false` | false | true | Ordinary |
|
|
| `--debug --quiet=false` | true | true | Debug |
|
|
| `--debug --progress=false` | true | true | Debug |
|
|
|
|
Aliases use the same canonical debug input. Tokens consumed as other flag
|
|
values or appearing after `--` keep their existing meaning. Invalid reporting
|
|
booleans remain usage failures without handler execution. Existing placement,
|
|
help, and input-preparation timing continue to apply.
|
|
|
|
Application code can use the bound value for diagnostic artifacts even when
|
|
quiet mode suppresses ordinary CLI output. Core continues to own reporting
|
|
visibility; applications own capture, redaction, file lifecycle, and any other
|
|
domain effects. No capture policy is imposed on Audita or other applications.
|
|
|
|
### Honor application binding settings, help, and aliases
|
|
|
|
OD-2 is resolved: honor ordinary application binding settings while keeping
|
|
core reporting selection independent. Application defaults and requiredness
|
|
affect the receiving binding; they do not select a reporting mode. Core continues
|
|
to resolve reporting from explicit CLI occurrences under the existing rules.
|
|
|
|
For example, a non-required binding with a true default receives
|
|
`Value=true, Set=false` when debug is omitted, while reporting remains ordinary
|
|
in the absence of mode flags. An explicit `--debug=false` overrides that default.
|
|
With `--debug --quiet`, the binding receives true while reporting is quiet.
|
|
Requiredness follows ordinary presence semantics: if required, omission is a
|
|
usage failure, while an explicit false satisfies the presence requirement.
|
|
An application default does not count as explicit input.
|
|
|
|
Honor the application's short spelling through existing alias and collision
|
|
rules. Both that spelling and other registered aliases feed the same canonical
|
|
debug input and reporting occurrence sequence.
|
|
|
|
Show one debug option in command help, combining the core reporting explanation
|
|
with any application-specific usage text. Clearly label an application default
|
|
that differs from core behavior, so a true application default does not imply
|
|
that debug reporting is enabled by default. Show application requiredness using
|
|
the existing help conventions. Keep ordinary boolean binding completion behavior
|
|
and metadata handling; this feature adds no special rejection of completion
|
|
settings. Completion suggestions do not change the shared boolean grammar.
|
|
|
|
This choice keeps ordinary `BoolFlag` settings useful without adding restrictions
|
|
solely for shared registration. The distinction between application input and
|
|
reporting selection must be clear in help and consumer guidance. Implement this
|
|
small combination directly; a general metadata-merging framework is unnecessary.
|
|
|
|
### Query the resolved reporting mode
|
|
|
|
Add a CommandKit-owned `ReportingMode` type with ordinary, quiet, verbose, and
|
|
debug values, and one canonical accessor:
|
|
|
|
```go
|
|
func (inv Invocation) ReportingMode() ReportingMode
|
|
```
|
|
|
|
Use `ReportingModeOrdinary`, `ReportingModeQuiet`, `ReportingModeVerbose`, and
|
|
`ReportingModeDebug` as the planned constant names, with ordinary as zero.
|
|
The accessor reads the existing selection without output or mutation. The mode
|
|
is final when the handler receives the invocation and remains its selection
|
|
after execution finishes. A manually constructed zero-value invocation returns
|
|
ordinary. Reads are compatible with concurrent reporting on that invocation;
|
|
this does not add concurrent dispatch support or extend writer lifetimes.
|
|
|
|
An application deliberately following reporting visibility can use:
|
|
|
|
```go
|
|
captureArtifacts := inv.ReportingMode() == commandkit.ReportingModeDebug
|
|
```
|
|
|
|
This reports the selected mode, not whether output was delivered successfully.
|
|
Progress and report format remain separate selections. Keep the public type
|
|
independent of internal/backend types and avoid a second mutable copy of the
|
|
resolved mode. A second accessor on `Reporter` is unnecessary for this scope.
|
|
|
|
## Implementation work
|
|
|
|
1. **Implement ordinary binding attachment and metadata handling.** Use the
|
|
selected `BoolFlag` form and the accepted application metadata rules above.
|
|
Preserve application defaults, presence, requiredness, and short spellings;
|
|
combine help without changing core reporting selection. Preserve ordinary
|
|
validation for unrelated names and bindings; do not broadly disable reserved
|
|
name or collision checks.
|
|
2. **Connect shared parsing to typed input.** Update declaration validation,
|
|
metadata bridging, and backend value extraction together. Register one
|
|
effective debug flag, retain canonical occurrence order and supplied
|
|
spellings, and deliver its values through normal input preparation. Keep
|
|
reporting reduction based on the same parsed occurrences, including for
|
|
commands that have no application debug binding. Reuse current mechanisms;
|
|
a general observer registry, alternate parser, or subscription lifecycle is
|
|
not needed for this feature.
|
|
3. **Preserve binding composition.** Review `CaptureFlags`, `FlagValues.ApplyTo`,
|
|
and `ApplySuppliedTo` in [flag_values.go](../../flag_values.go). A shared
|
|
binding should participate through the existing identity and presence
|
|
machinery. Review `RenameFlag` if a special binding marker is introduced:
|
|
renaming to an ordinary application name must not accidentally keep reading
|
|
core debug input. Avoid adding separate storage or application callbacks just
|
|
to carry this boolean.
|
|
4. **Expose the mode query.** Reuse reporter state and its synchronization as
|
|
appropriate; document the zero-value, invocation lifetime, and concurrent-read
|
|
behavior. Do not expose backend objects or add public mutation APIs.
|
|
5. **Update canonical documentation when implemented.** Update binding and
|
|
invocation GoDoc, the reserved-name wording in `FlagMeta`, and the
|
|
[CLI reference](../cli.md#placement-and-aliases). Add a short example to the
|
|
[consumer guide](../consumers/guide.md#invocation-reporting) contrasting a
|
|
bound debug boolean with an explicit mode query. Explain application effects
|
|
in application help using the accepted metadata rules. Record the core API
|
|
addition in the applicable release note. Retire this roadmap through the
|
|
normal documentation lifecycle when complete.
|
|
|
|
This is core work. It does not require ConfigKit or PromptKit API additions or
|
|
adoption of Audita's artifact implementation. Binding other core flags, adding
|
|
mode setters, or creating a general flag-sharing framework is not part of this
|
|
sprint; that scope limit is not a permanent prohibition on later capabilities.
|
|
|
|
## Validation and completion checklist
|
|
|
|
Follow the [testing policy](../policy/testing.md): test the public behavior and
|
|
reuse existing parser and reporting coverage rather than duplicate it wholesale.
|
|
The table above supplies representative boundary expectations, not a request
|
|
for separate copies of the same cases at every layer.
|
|
|
|
- [ ] A registered application command receives the shared debug boolean and
|
|
presence through normal typed input preparation, including when quiet or
|
|
verbose becomes the resolved reporting mode.
|
|
- [ ] The public query returns the selected mode without changing visibility;
|
|
cover zero value, retained invocation, and fresh selection on subsequent runs.
|
|
- [ ] Focused coverage establishes safe mode reads during existing concurrent
|
|
reporter use, without asserting concurrent dispatch support.
|
|
- [ ] Exercise aliases, explicit false, repeated values, invalid booleans, and
|
|
option-looking operands/values where they establish the new binding boundary.
|
|
Preserve existing failure precedence and no-handler-on-parse-failure behavior.
|
|
- [ ] A command with both shared debug and ordinary flags receives the correct
|
|
values; help and completion describe one effective debug option. Exercise
|
|
representative capture/application composition and any affected rename path.
|
|
- [ ] Cover a true application default without debug reporting, explicit false
|
|
overriding that default, and ordinary requiredness/presence behavior. Help
|
|
combines core and application explanations and distinguishes the application
|
|
default; local short spellings use existing collision and alias rules.
|
|
- [ ] Replace obsolete blanket rejection assertions for the allowed binding
|
|
form. Preserve ordinary metadata handling without new debug-specific
|
|
restrictions beyond the selected boolean binding contract.
|
|
- [ ] Run focused binding/parser/reporter tests, then the core suite and aligned
|
|
integration suites using the [developer guide](../development.md). The shared
|
|
parser change justifies checking that standard integration commands still
|
|
register and execute. No live providers or Audita processing tests are needed.
|
|
- [ ] GoDoc and consumer guidance distinguish boolean input from reporting
|
|
mode, and canonical docs describe the implemented registration exception.
|
|
|
|
For this documentation pass, review baseline accuracy, scope, links, and
|
|
whitespace only. Implementation and the unchecked items above remain future work.
|