Document invocation reporting contracts
This commit is contained in:
@@ -8,13 +8,17 @@ modules, so applications choose which upstream libraries they add.
|
|||||||
The core captures reusable command declarations, validates installation batches
|
The core captures reusable command declarations, validates installation batches
|
||||||
before changing an application's registry, converts typed inputs before
|
before changing an application's registry, converts typed inputs before
|
||||||
constructing them, and returns outcomes without exiting the process. Its
|
constructing them, and returns outcomes without exiting the process. Its
|
||||||
[consumer guide](docs/consumers/guide.md) covers declaration and invocation.
|
[consumer guide](docs/consumers/guide.md) covers declaration, invocation
|
||||||
|
reporting, and migration. 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.
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
| Module | Package | Provides |
|
| Module | Package | Provides |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `gitea.maximumdirect.net/eric/CommandKit` | `commandkit` | Typed commands, bindings, execution, outcomes, help, and version. |
|
| `gitea.maximumdirect.net/eric/CommandKit` | `commandkit` | Typed commands, bindings, execution reporting and outcomes, help, and version. |
|
||||||
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | `ckconfig` | ConfigKit-backed `config` scopes, including configuration source evidence. |
|
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig` | `ckconfig` | ConfigKit-backed `config` scopes, including configuration source evidence. |
|
||||||
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | `ckprompt` | PromptKit engine configuration/comparison, five catalogs, named inspection, requirements discovery, concrete request validation, and native smoke tests. |
|
| `gitea.maximumdirect.net/eric/CommandKit/integrations/ckprompt` | `ckprompt` | PromptKit engine configuration/comparison, five catalogs, named inspection, requirements discovery, concrete request validation, and native smoke tests. |
|
||||||
|
|
||||||
|
|||||||
3
doc.go
3
doc.go
@@ -1,6 +1,7 @@
|
|||||||
// Package commandkit provides the core instance-owned CLI dispatcher, typed
|
// Package commandkit provides the core instance-owned CLI dispatcher, typed
|
||||||
// command declarations, application-owned command and flag aliases, input
|
// command declarations, application-owned command and flag aliases, input
|
||||||
// bindings, and invocation outcomes. New and App.Register accept canonical
|
// 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
|
// Command declarations and RoutingRule declarations together. Optional
|
||||||
// integration modules provide ConfigKit and PromptKit-specific commands;
|
// integration modules provide ConfigKit and PromptKit-specific commands;
|
||||||
// importing those modules does not install their commands.
|
// importing those modules does not install their commands.
|
||||||
|
|||||||
112
docs/cli.md
112
docs/cli.md
@@ -66,6 +66,93 @@ version: dev
|
|||||||
revision: ""
|
revision: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
|
||||||
|
CommandKit applies one shared reporting policy to application handlers,
|
||||||
|
integrations, help, version, and CommandKit's own invocation diagnostics. The
|
||||||
|
caller passes result and diagnostic writers to `App.Execute`; substantive
|
||||||
|
results go to `Streams.Out`, and categorized messages, terminal explanations,
|
||||||
|
and usage guidance go to `Streams.Err`.
|
||||||
|
|
||||||
|
### Modes and visibility
|
||||||
|
|
||||||
|
Each invocation starts in ordinary mode. `--quiet`, `--verbose`, and `--debug`
|
||||||
|
are mutually exclusive; the last enabled occurrence selects the mode. They
|
||||||
|
accept presence or an explicit boolean value. A `false` occurrence clears the
|
||||||
|
selected mode only when it names the current mode, returning to ordinary mode;
|
||||||
|
it does not restore an earlier selection. Invalid boolean values are usage
|
||||||
|
errors, even if a later flag would select another mode.
|
||||||
|
|
||||||
|
| Category | `--quiet` | No mode flag | `--verbose` | `--debug` |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| Substantive result | Suppressed | Shown | Shown | Shown |
|
||||||
|
| Terminal failure | Shown | Shown | Shown | Shown |
|
||||||
|
| Warning | Suppressed | Suppressed | Shown | Shown |
|
||||||
|
| Info | Suppressed | Suppressed | Shown | Shown |
|
||||||
|
| Debug | Suppressed | Suppressed | Suppressed | Shown |
|
||||||
|
| Progress, unless enabled explicitly | Suppressed | Suppressed | Suppressed | Shown |
|
||||||
|
|
||||||
|
`--progress` independently enables Progress; `--progress=false` disables it.
|
||||||
|
Both accept the existing boolean syntax, and the last occurrence wins. An
|
||||||
|
explicit setting overrides the mode default, except quiet always suppresses
|
||||||
|
Progress. Without an explicit setting, debug enables Progress; ordinary and
|
||||||
|
verbose modes leave it disabled. Progress does not enable Info, Warning, or
|
||||||
|
Debug.
|
||||||
|
|
||||||
|
### Placement and aliases
|
||||||
|
|
||||||
|
Reporting flags are available on application commands, the root, canonical
|
||||||
|
groups, help, version, and alias-only discovery help. Place them after the
|
||||||
|
complete command path; they may be interspersed with operands after that path.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```text
|
||||||
|
example export --quiet
|
||||||
|
example config show --verbose
|
||||||
|
example promptkit test all --debug --progress=false
|
||||||
|
example help config show --quiet
|
||||||
|
example version --quiet
|
||||||
|
```
|
||||||
|
|
||||||
|
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`, and
|
||||||
|
`--progress`; application declarations cannot reuse them. 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.
|
||||||
|
|
||||||
|
### Channels and messages
|
||||||
|
|
||||||
|
Substantive reports use the result destination. Warnings, Info, Progress,
|
||||||
|
Debug, terminal explanations, and usage guidance use the diagnostic destination.
|
||||||
|
Simple Warning, Debug, and terminal failure messages begin with `WARN:`,
|
||||||
|
`DEBUG:`, and `ERROR:` respectively. Info, Progress, and substantive results
|
||||||
|
have no prefix. For multiline messages, the prefix appears on the opening line;
|
||||||
|
native structured details keep their own formatting without duplicate labels.
|
||||||
|
Progress is streamed as unprefixed lines; terminal redraw and progress bars are
|
||||||
|
not provided. A failed outcome with no message or detail uses the fallback
|
||||||
|
`ERROR: Command failed.`.
|
||||||
|
|
||||||
|
Quiet mode suppresses successful help and version output, as it does other
|
||||||
|
substantive results. Usage guidance and routing, parsing, and operational
|
||||||
|
failures remain visible in every mode. A recovered problem is reported only if
|
||||||
|
the application chooses to submit a Warning; an error cause by itself does not
|
||||||
|
create a message.
|
||||||
|
|
||||||
|
### Presentation failures
|
||||||
|
|
||||||
|
CommandKit continues rendering substantive output under quiet mode through a
|
||||||
|
discard destination. This suppresses writes to the caller's result writer while
|
||||||
|
still detecting report preparation, encoding, or rendering failures. An
|
||||||
|
intentional suppression is not a delivery failure. A failure while rendering or
|
||||||
|
writing requested content is retained in the returned `Outcome` and makes an
|
||||||
|
otherwise successful or usage invocation operational with status `1`. A domain
|
||||||
|
classification and its nonzero status are preserved; a zero-status domain
|
||||||
|
outcome becomes status `1` when presentation fails. Earlier bytes already
|
||||||
|
written remain visible.
|
||||||
|
|
||||||
## Registered command syntax
|
## Registered command syntax
|
||||||
|
|
||||||
Options are parsed after the complete command path and may be interspersed with
|
Options are parsed after the complete command path and may be interspersed with
|
||||||
@@ -223,8 +310,8 @@ interrupt the native value. Existing native markers and leading comments are
|
|||||||
retained; documents without a marker receive one. Scope labels containing line
|
retained; documents without a marker receive one. Scope labels containing line
|
||||||
control characters are quoted to keep them on one comment line. A provider
|
control characters are quoted to keep them on one comment line. A provider
|
||||||
failure leaves the output stream empty. A rendering or output failure may leave
|
failure leaves the output stream empty. A rendering or output failure may leave
|
||||||
an aggregate prefix, and the outcome reports
|
an aggregate prefix; `Outcome.Presentation.Output` records incomplete delivery
|
||||||
incomplete report delivery.
|
and the destination or rendering error.
|
||||||
|
|
||||||
### List configuration sources
|
### List configuration sources
|
||||||
|
|
||||||
@@ -390,8 +477,9 @@ again.
|
|||||||
The complete report is prepared before writing. Report preparation failures and
|
The complete report is prepared before writing. Report preparation failures and
|
||||||
cancellation observed before report delivery starts leave CommandKit's report
|
cancellation observed before report delivery starts leave CommandKit's report
|
||||||
output empty. Once writing starts, CommandKit does not interrupt the supplied
|
output empty. Once writing starts, CommandKit does not interrupt the supplied
|
||||||
writer or roll back delivered bytes. A write error or short write uses the
|
writer or roll back delivered bytes. A write error or short write is recorded
|
||||||
existing incomplete-report delivery outcome and can leave partial output.
|
as incomplete delivery in `Outcome.Presentation.Output` and can leave partial
|
||||||
|
output.
|
||||||
|
|
||||||
## PromptKit definition inspection
|
## PromptKit definition inspection
|
||||||
|
|
||||||
@@ -607,8 +695,9 @@ execution. See PromptKit's
|
|||||||
Builder, engine-loading, and native validation errors use the operational path
|
Builder, engine-loading, and native validation errors use the operational path
|
||||||
(status `1`) with supported error identity and acquired diagnostics retained.
|
(status `1`) with supported error identity and acquired diagnostics retained.
|
||||||
Malformed syntax, missing operands, and unsupported formats use usage status
|
Malformed syntax, missing operands, and unsupported formats use usage status
|
||||||
`2`. Successful diagnostics and report-delivery failures follow the common
|
`2`. Successful diagnostics use the common reporting policy. Report delivery
|
||||||
delivery contract.
|
failures are recorded in `Outcome.Presentation.Output`, separately from the
|
||||||
|
operation cause.
|
||||||
|
|
||||||
### PromptKit catalogs
|
### PromptKit catalogs
|
||||||
|
|
||||||
@@ -802,8 +891,8 @@ outcome. Operation errors use operational status `1`; aggregate runs continue
|
|||||||
after individual errors, retain their reports and ordered error text, and join
|
after individual errors, retain their reports and ordered error text, and join
|
||||||
causes for supported `errors.Is`/`errors.As` access. Cancellation stops later
|
causes for supported `errors.Is`/`errors.As` access. Cancellation stops later
|
||||||
operations and preserves results already acquired. Report encoding or delivery
|
operations and preserves results already acquired. Report encoding or delivery
|
||||||
failures use the common incomplete-report delivery outcome and retain operation
|
failures are recorded in `Outcome.Presentation.Output`, separately from
|
||||||
causes where applicable. Syntax, operand, unsupported format, and conflicting
|
operation causes. Syntax, operand, unsupported format, and conflicting
|
||||||
namespace selection are usage status `2`.
|
namespace selection are usage status `2`.
|
||||||
|
|
||||||
Native configuration, selection, and diagnostic meanings remain owned by
|
Native configuration, selection, and diagnostic meanings remain owned by
|
||||||
@@ -816,4 +905,9 @@ and [engine API](https://gitea.maximumdirect.net/eric/promptkit/src/commit/9178f
|
|||||||
CommandKit usage failures use status `2`; operational failures use status `1`.
|
CommandKit usage failures use status `2`; operational failures use status `1`.
|
||||||
Successful operations use status `0`. Application handlers may return a domain
|
Successful operations use status `0`. Application handlers may return a domain
|
||||||
classification and status of their choice, which `Execute` preserves. The caller
|
classification and status of their choice, which `Execute` preserves. The caller
|
||||||
chooses how to map an outcome to process exit.
|
chooses how to map an outcome to process exit. A rendering or delivery failure
|
||||||
|
changes a successful or usage outcome to operational status `1`. A domain
|
||||||
|
outcome keeps its classification and nonzero status; a zero-status domain
|
||||||
|
outcome becomes `1` if presentation fails. The returned `Outcome.Presentation`
|
||||||
|
records output and diagnostic delivery observations separately from its
|
||||||
|
operation `Cause`.
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ func Greeting() commandkit.Command {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
|
Run: func(invocation commandkit.Invocation, input GreetInput) commandkit.Outcome {
|
||||||
_, _ = fmt.Fprintln(invocation.Streams.Out, input.Count.Value)
|
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()
|
return commandkit.Success()
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -85,6 +87,49 @@ values convert before input construction. A command's `NewInput` creates input
|
|||||||
only when execution reaches it; help does not construct caller input or run
|
only when execution reaches it; help does not construct caller input or run
|
||||||
provider callbacks.
|
provider callbacks.
|
||||||
|
|
||||||
|
## Invocation reporting
|
||||||
|
|
||||||
|
`Invocation.Reporter()` supplies the reporter for the current handler. Use
|
||||||
|
`Output()` or `RenderOutput()` for substantive results; use `Warn`, `Info`,
|
||||||
|
`Progress`, and `Debug` for categorized messages. Queue a summary with
|
||||||
|
`AtEnd().Info` when it belongs after the handler returns. The
|
||||||
|
[CLI reference](../cli.md#reporting) owns flag grammar, visibility, prefixes,
|
||||||
|
and status behavior.
|
||||||
|
|
||||||
|
Return terminal text with `Failure(message, details...)`, `Usage(message,
|
||||||
|
details...)`, or `WithExplanation` on a domain outcome. Attach an optional Go
|
||||||
|
error separately with `WithCause`. A cause is preserved for inspection, but it
|
||||||
|
does not choose the outcome or become user-facing text. Rendering callbacks
|
||||||
|
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.
|
||||||
|
|
||||||
|
```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()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
### Migrating from the previous reporting API
|
||||||
|
|
||||||
|
| Previous API | Current API |
|
||||||
|
| --- | --- |
|
||||||
|
| `invocation.Streams.Out` / `.Err` | `invocation.Reporter().Output()` and categorized reporter methods. `Streams` remains the argument to `App.Execute`. |
|
||||||
|
| `Failure(err)` / `Usage(err)` | `Failure("operator-facing explanation").WithCause(err)` / `Usage("usage explanation").WithCause(err)`. Choose the explanation deliberately; the cause alone is not printed. |
|
||||||
|
| `Outcome.Diagnostics` or terminal `SeverityError` | Submit independent messages through reporter methods. Put failure context in `Explanation`; provider `Acquired.Diagnostics` remains passive data for the owning integration to submit. |
|
||||||
|
| `ReportIncomplete`, `DiagnosticDelivery`, or `DeliveryError` | Inspect `Outcome.Presentation.Output` and `.Diagnostics`, including each `DeliveryResult.State`, `RenderError`, and `WriteError`. |
|
||||||
|
|
||||||
## Application-owned aliases
|
## Application-owned aliases
|
||||||
|
|
||||||
Pass commands and aliases together as declarations. Integration factories can
|
Pass commands and aliases together as declarations. Integration factories can
|
||||||
@@ -257,10 +302,11 @@ application-owned `session restore` command.
|
|||||||
## Outcomes and ownership
|
## Outcomes and ownership
|
||||||
|
|
||||||
Core classifies usage and operational failures while preserving application
|
Core classifies usage and operational failures while preserving application
|
||||||
domain outcomes and supported error identity. Report and diagnostic delivery
|
domain outcomes and supported error identity. Applications choose domain
|
||||||
errors remain inspectable separately from the operation cause. The caller owns
|
classification and status. A terminal explanation is presented separately from
|
||||||
process startup, signal handling, and exit mapping; `Execute` never exits the
|
the optional operation cause, while report and diagnostic delivery observations
|
||||||
process.
|
are available in `Outcome.Presentation`. The caller owns process startup,
|
||||||
|
signal handling, and exit mapping; `Execute` never exits the process.
|
||||||
|
|
||||||
Go declarations and GoDoc own exact exported contracts. ConfigKit owns
|
Go declarations and GoDoc own exact exported contracts. ConfigKit owns
|
||||||
configuration decoding, validation, and provenance. PromptKit owns prompt
|
configuration decoding, validation, and provenance. PromptKit owns prompt
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
CommandKit is distributed as a core Go module and two optional integration
|
CommandKit is distributed as a core Go module and two optional integration
|
||||||
modules. Core owns captured declarations, typed input preparation, installation,
|
modules. Core owns captured declarations, typed input preparation, installation,
|
||||||
dispatch, outcomes, help, and version. `integrations/ckconfig` owns ConfigKit
|
dispatch, invocation reporting and outcomes, help, and version.
|
||||||
scope adaptation and reports; `integrations/ckprompt` owns PromptKit engine,
|
`integrations/ckconfig` owns ConfigKit scope adaptation and reports;
|
||||||
|
`integrations/ckprompt` owns PromptKit engine,
|
||||||
definition inspection, requirements discovery, and concrete request validation.
|
definition inspection, requirements discovery, and concrete request validation.
|
||||||
The maintained [consumer guide](consumers/guide.md) links to the three maintained
|
The maintained [consumer guide](consumers/guide.md) links to the three maintained
|
||||||
consumers.
|
consumers.
|
||||||
@@ -53,6 +54,7 @@ For application-owned aliases, use the
|
|||||||
| Task | Read |
|
| Task | Read |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Implemented CLI behavior | [CLI reference](cli.md) |
|
| Implemented CLI behavior | [CLI reference](cli.md) |
|
||||||
|
| Invocation reporting | [CLI reporting contract](cli.md#reporting), [consumer guide](consumers/guide.md#invocation-reporting), core GoDoc, [reporting roadmap](roadmap/reporting.md), and [ADR 0014](adr/0014-invocation-reporting.md) |
|
||||||
| Application-owned aliases | [CLI reference](cli.md#application-owned-aliases), [Go declarations and GoDoc](../command.go), [consumer guide](consumers/guide.md#application-owned-aliases), and [ADR 0013](adr/0013-application-alias-routing.md) |
|
| Application-owned aliases | [CLI reference](cli.md#application-owned-aliases), [Go declarations and GoDoc](../command.go), [consumer guide](consumers/guide.md#application-owned-aliases), and [ADR 0013](adr/0013-application-alias-routing.md) |
|
||||||
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs |
|
| Public API usage and standard-suite wiring | [Consumer guide](consumers/guide.md), [ckconfig package](../integrations/ckconfig/doc.go), [ckprompt package](../integrations/ckprompt/doc.go), and applicable ADRs |
|
||||||
| Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
|
| Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md), refined by [ADR 0011](adr/0011-captured-declarations-and-installation.md) |
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ this page inventories the implemented owners.
|
|||||||
|
|
||||||
The root facade owns captured canonical command declarations, application-owned
|
The root facade owns captured canonical command declarations, application-owned
|
||||||
routing rules, binding conversion, invocation coordination, the per-App
|
routing rules, binding conversion, invocation coordination, the per-App
|
||||||
registries, standard help/version commands, and outcome/diagnostic delivery.
|
registries, standard help/version commands, invocation reporting, and outcome
|
||||||
|
finalization.
|
||||||
Its dependency graph has no ConfigKit or PromptKit integration dependency.
|
Its dependency graph has no ConfigKit or PromptKit integration dependency.
|
||||||
Applications provide typed callbacks and install routing rules alongside the
|
Applications provide typed callbacks and install routing rules alongside the
|
||||||
complete canonical command tree through the same batch API.
|
complete canonical command tree through the same batch API.
|
||||||
@@ -25,6 +26,30 @@ successful registration invalidates the snapshot for a later invocation. The
|
|||||||
root package owns app input and callback execution, not provider configuration
|
root package owns app input and callback execution, not provider configuration
|
||||||
semantics.
|
semantics.
|
||||||
|
|
||||||
|
Each execution creates one reporter backed by the caller's result and diagnostic
|
||||||
|
writers. The Cobra adapter returns parsed values, flag spellings, and reporting
|
||||||
|
flag occurrences. Core reduces those occurrences in entered order after route
|
||||||
|
resolution, applies the final mode and progress selection, and presents any
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
closes its handles before `Execute` returns. It records rendering and write
|
||||||
|
errors separately for result and diagnostic destinations; the returned
|
||||||
|
`Outcome.Presentation` exposes those observations independently from the
|
||||||
|
operation cause. The reporter does not retain a transcript and does not close
|
||||||
|
or flush caller-owned writers.
|
||||||
|
|
||||||
|
Internally, one reporting-state mutex guards visibility, queued messages,
|
||||||
|
destination state, and delivery errors while serializing reporter operations
|
||||||
|
and writes. Rendering callbacks execute within that coordination boundary, so
|
||||||
|
they must not recursively submit or render through the same reporter. This is
|
||||||
|
an implementation detail supporting the callback contract; the mutex does not
|
||||||
|
coordinate writes made outside the reporter.
|
||||||
|
|
||||||
## `internal/alias` and `internal/commandpath`
|
## `internal/alias` and `internal/commandpath`
|
||||||
|
|
||||||
`internal/commandpath` provides shared path parsing and token operations used by
|
`internal/commandpath` provides shared path parsing and token operations used by
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
CommandKit v0.3.0 adds application-owned command and flag aliases. This
|
CommandKit v0.3.0 adds application-owned command and flag aliases and shared
|
||||||
pre-1.0 minor release also updates the installation declaration type and
|
invocation reporting. This pre-1.0 minor release also updates the installation
|
||||||
Invocation struct shape; review the migration guidance before upgrading.
|
declaration type and Invocation struct shape, replaces the error-first outcome
|
||||||
|
and diagnostic-delivery APIs, and reserves reporting flag names; review the
|
||||||
|
migration guidance before upgrading.
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
@@ -17,6 +19,14 @@ Invocation struct shape; review the migration guidance before upgrading.
|
|||||||
`EnteredPath` and `CanonicalPath`.
|
`EnteredPath` and `CanonicalPath`.
|
||||||
- Interpret a canonical short value flag such as `-c=` as an explicitly
|
- Interpret a canonical short value flag such as `-c=` as an explicitly
|
||||||
supplied empty value, consistent with `--color=` and `-c ""`.
|
supplied empty value, consistent with `--color=` and `-c ""`.
|
||||||
|
- Obtain an invocation-scoped `Reporter` from each handler's `Invocation` for
|
||||||
|
substantive output, Warning/Info/Progress/Debug messages, deferred messages,
|
||||||
|
and managed report rendering. The shared `--quiet`, `--verbose`, `--debug`,
|
||||||
|
and `--progress` flags apply across core and integration commands.
|
||||||
|
- Return terminal explanation text with `Failure`, `Usage`, or
|
||||||
|
`Outcome.WithExplanation`; attach an optional operation error separately with
|
||||||
|
`Outcome.WithCause`. Returned `Outcome.Presentation` records output and
|
||||||
|
diagnostic delivery observations without changing the operation cause.
|
||||||
|
|
||||||
## Compatibility and migration
|
## Compatibility and migration
|
||||||
|
|
||||||
@@ -29,10 +39,26 @@ values whose parameter type is `...Command`, including wrappers assigned from
|
|||||||
`New` or `Register`, must update their signature to `...Declaration`.
|
`New` or `Register`, must update their signature to `...Declaration`.
|
||||||
|
|
||||||
Adding private route fields to `Invocation` means positional struct literals no
|
Adding private route fields to `Invocation` means positional struct literals no
|
||||||
longer compile. Use keyed fields, for example
|
longer compile. `Invocation` no longer contains `Streams`; `App.Execute` supplies
|
||||||
`commandkit.Invocation{Context: ctx, Streams: streams}`, when constructing an
|
the reporter and route paths to handlers. `Streams` remains the argument to
|
||||||
Invocation outside command execution. CommandKit populates the route fields for
|
`App.Execute`, where the caller owns the result and diagnostic writers.
|
||||||
executed handlers.
|
|
||||||
|
Handlers that used `invocation.Streams.Out` or `.Err` should use
|
||||||
|
`invocation.Reporter().Output()` or the categorized reporting methods. Replace
|
||||||
|
`Failure(err)` and `Usage(err)` with an operator-facing explanation and an
|
||||||
|
optional `.WithCause(err)`; causes alone are not rendered. Replace
|
||||||
|
`Outcome.Diagnostics` submissions and terminal `SeverityError` records with
|
||||||
|
reporter messages and an `Outcome` explanation. Provider-returned
|
||||||
|
`Acquired.Diagnostics` remain passive data for the owning integration to
|
||||||
|
submit. Replace `ReportIncomplete`, `DiagnosticDelivery`, and `DeliveryError`
|
||||||
|
with `Outcome.Presentation.Output` and `.Diagnostics`, whose `DeliveryResult`
|
||||||
|
contains a state plus first render and write errors.
|
||||||
|
|
||||||
|
The long flags `--quiet`, `--verbose`, `--debug`, and `--progress` are reserved
|
||||||
|
for CommandKit reporting and cannot be declared by applications. Application
|
||||||
|
aliases may target them. See the current [CLI reporting contract](../cli.md#reporting)
|
||||||
|
and [consumer migration guide](../consumers/guide.md#invocation-reporting) for
|
||||||
|
their behavior and API examples.
|
||||||
|
|
||||||
The consumer minimum remains Go 1.26.0 and the maintainer release toolchain
|
The consumer minimum remains Go 1.26.0 and the maintainer release toolchain
|
||||||
remains Go 1.26.8. Core v0.3.0 must be published before preparing dependent
|
remains Go 1.26.8. Core v0.3.0 must be published before preparing dependent
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Invocation reporting implementation plan
|
# Invocation reporting implementation plan
|
||||||
|
|
||||||
Status: Stages 1–18 complete. Stage 19 is next.
|
Status: Stages 1–19 complete. Stage 20 is next.
|
||||||
|
|
||||||
## Objective and authority
|
## Objective and authority
|
||||||
|
|
||||||
@@ -719,7 +719,7 @@ on either optional integration module.
|
|||||||
|
|
||||||
## Stage 19: Update canonical documentation and compatibility guidance
|
## Stage 19: Update canonical documentation and compatibility guidance
|
||||||
|
|
||||||
Status: pending.
|
Status: complete.
|
||||||
|
|
||||||
1. Update public Go declarations/GoDoc for exact reporter, outcome, provider,
|
1. Update public Go declarations/GoDoc for exact reporter, outcome, provider,
|
||||||
lifecycle, cause, and presentation-observation contracts. Describe callback
|
lifecycle, cause, and presentation-observation contracts. Describe callback
|
||||||
@@ -749,6 +749,15 @@ Validation: review prose against implemented behavior, check local links and
|
|||||||
fragments, and run the Markdown whitespace checks from the developer guide.
|
fragments, and run the Markdown whitespace checks from the developer guide.
|
||||||
Current contract documentation must no longer present the removed APIs as valid.
|
Current contract documentation must no longer present the removed APIs as valid.
|
||||||
|
|
||||||
|
Completion: updated exported GoDoc, the CLI reference, consumer migration
|
||||||
|
guidance, README, integration package documentation, developer guide, internal
|
||||||
|
overview, and the unpublished core v0.3.0 note. Current contracts direct callers
|
||||||
|
to the invocation reporter and keep operation causes separate from explanations
|
||||||
|
and presentation observations. Reviewed the prose against the implementation
|
||||||
|
and selected reporting policy; `go doc` checks, local Markdown link and fragment
|
||||||
|
checks, and both Markdown whitespace checks pass. Historical integration release
|
||||||
|
notes, accepted ADRs, and deferred-work records remain unchanged.
|
||||||
|
|
||||||
## Stage 20: Validate the complete end state and finish
|
## Stage 20: Validate the complete end state and finish
|
||||||
|
|
||||||
Status: pending.
|
Status: pending.
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ diagnostic boundary, fallback explanations, and rendering callback boundary
|
|||||||
below are also selected. Architectural preparation is complete:
|
below are also selected. Architectural preparation is complete:
|
||||||
[ADR 0014](../adr/0014-invocation-reporting.md) is accepted, and the
|
[ADR 0014](../adr/0014-invocation-reporting.md) is accepted, and the
|
||||||
[architecture policy](../policy/architecture.md) is aligned. Implementation has
|
[architecture policy](../policy/architecture.md) is aligned. Implementation has
|
||||||
not started; implementation, validation, and maintained consumer examples remain.
|
started. Stages 1–19 are complete; final validation remains. The
|
||||||
The [implementation plan](implementation.md) owns stage order and execution
|
[implementation plan](implementation.md) owns stage order and execution
|
||||||
instructions.
|
instructions.
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ import (
|
|||||||
|
|
||||||
// Execute parses and dispatches one invocation. args excludes the executable
|
// Execute parses and dispatches one invocation. args excludes the executable
|
||||||
// name. Supplied values are converted before command input construction; help
|
// name. Supplied values are converted before command input construction; help
|
||||||
// does not construct caller inputs or run acquisition callbacks. CommandKit
|
// does not construct caller inputs or run acquisition callbacks. It applies the
|
||||||
// writes diagnostics to streams.Err and leaves process exit to the caller. A
|
// parsed reporting selection, finalizes invocation presentation, and returns
|
||||||
// nil context returns an operational failure, and nil streams are replaced with
|
// the resulting Outcome without exiting the process. Supplied streams remain
|
||||||
// io.Discard.
|
// caller-owned; nil destinations are replaced with io.Discard. A nil context
|
||||||
|
// returns an operational failure.
|
||||||
func (a *App) Execute(ctx context.Context, args []string, streams Streams) Outcome {
|
func (a *App) Execute(ctx context.Context, args []string, streams Streams) Outcome {
|
||||||
current := newExecution(a, ctx, streams)
|
current := newExecution(a, ctx, streams)
|
||||||
if a == nil {
|
if a == nil {
|
||||||
|
|||||||
19
identity.go
19
identity.go
@@ -18,8 +18,11 @@ type Identity struct {
|
|||||||
Revision string
|
Revision string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Streams contains the output destinations associated with a command
|
// Streams contains the caller-owned output destinations associated with an
|
||||||
// invocation.
|
// invocation. Out receives substantive results; Err receives messages,
|
||||||
|
// terminal explanations, usage guidance, and CommandKit diagnostics. Nil
|
||||||
|
// destinations are replaced with io.Discard. CommandKit does not close or flush
|
||||||
|
// supplied writers.
|
||||||
type Streams struct {
|
type Streams struct {
|
||||||
// Out receives help and command reports.
|
// Out receives help and command reports.
|
||||||
Out io.Writer
|
Out io.Writer
|
||||||
@@ -37,10 +40,11 @@ func normalizeStreams(streams Streams) Streams {
|
|||||||
return streams
|
return streams
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invocation provides execution context and reporting to a command handler.
|
// Invocation provides execution context and invocation-scoped reporting to a
|
||||||
// For command aliases, EnteredPath and CanonicalPath expose the route the
|
// command handler. Execute finalizes its reporter before returning. For command
|
||||||
// caller used and the selected canonical command path. Both omit the
|
// aliases, EnteredPath and CanonicalPath expose the route the caller used and
|
||||||
// executable name, flags, and operands.
|
// the selected canonical command path. Both omit the executable name, flags,
|
||||||
|
// and operands.
|
||||||
type Invocation struct {
|
type Invocation struct {
|
||||||
// Context carries caller cancellation and request-scoped values.
|
// Context carries caller cancellation and request-scoped values.
|
||||||
Context context.Context
|
Context context.Context
|
||||||
@@ -50,7 +54,8 @@ type Invocation struct {
|
|||||||
canonicalPath string
|
canonicalPath string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reporter returns the reporting facility for this invocation.
|
// Reporter returns the reporting facility supplied for this invocation. A
|
||||||
|
// manually constructed Invocation has no reporter.
|
||||||
func (inv Invocation) Reporter() *Reporter { return inv.reporter }
|
func (inv Invocation) Reporter() *Reporter { return inv.reporter }
|
||||||
|
|
||||||
// EnteredPath returns the command path used to invoke the selected command,
|
// EnteredPath returns the command path used to invoke the selected command,
|
||||||
|
|||||||
@@ -3,5 +3,7 @@
|
|||||||
// through the core commandkit package. Applications can install CommandKit
|
// through the core commandkit package. Applications can install CommandKit
|
||||||
// RoutingRule declarations alongside it through commandkit.New or
|
// RoutingRule declarations alongside it through commandkit.New or
|
||||||
// App.Register. Source reports preserve ConfigKit's destination, placement,
|
// App.Register. Source reports preserve ConfigKit's destination, placement,
|
||||||
// and version-check evidence; importing ckconfig alone installs no commands.
|
// and version-check 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
|
package ckconfig
|
||||||
|
|||||||
@@ -4,5 +4,7 @@
|
|||||||
// canonical commandkit.Command declarations. Applications can install
|
// canonical commandkit.Command declarations. Applications can install
|
||||||
// commandkit.RoutingRule aliases alongside them through commandkit.New or
|
// commandkit.RoutingRule aliases alongside them through commandkit.New or
|
||||||
// App.Register. Importing ckprompt installs neither family; callers compose its
|
// App.Register. Importing ckprompt installs neither family; callers compose its
|
||||||
// declarations with core and ckconfig explicitly.
|
// 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.
|
||||||
package ckprompt
|
package ckprompt
|
||||||
|
|||||||
58
outcome.go
58
outcome.go
@@ -6,7 +6,8 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Severity classifies a nonterminal diagnostic.
|
// Severity classifies a nonterminal provider diagnostic. Terminal failure
|
||||||
|
// context belongs in an Outcome explanation instead.
|
||||||
type Severity string
|
type Severity string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -48,13 +49,18 @@ const (
|
|||||||
DeliveryIncomplete
|
DeliveryIncomplete
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrReporterClosed is returned when a reporting handle is used after invocation finalization.
|
// ErrReporterClosed is returned when a reporting handle is used after
|
||||||
|
// invocation finalization.
|
||||||
var ErrReporterClosed = errors.New("reporter is closed")
|
var ErrReporterClosed = errors.New("reporter is closed")
|
||||||
|
|
||||||
// Detail renders optional content to the supplied writer.
|
// Detail renders optional content to the writer supplied by the reporter.
|
||||||
|
// Use that writer only during the callback. A callback must not submit another
|
||||||
|
// message, queue deferred work, or start another rendering operation through
|
||||||
|
// the same invocation's reporter.
|
||||||
type Detail func(io.Writer) error
|
type Detail func(io.Writer) error
|
||||||
|
|
||||||
// Explanation contains terminal content for a failed outcome.
|
// Explanation contains terminal content for a failed outcome. CommandKit
|
||||||
|
// presents it during invocation finalization, including in quiet mode.
|
||||||
type Explanation struct {
|
type Explanation struct {
|
||||||
// Message is the literal opening text.
|
// Message is the literal opening text.
|
||||||
Message string
|
Message string
|
||||||
@@ -62,7 +68,9 @@ type Explanation struct {
|
|||||||
Details []Detail
|
Details []Detail
|
||||||
}
|
}
|
||||||
|
|
||||||
// PresentationResult records delivery observations for the two output channels.
|
// PresentationResult records output and diagnostic delivery observations
|
||||||
|
// populated by CommandKit during invocation finalization. It is not a message
|
||||||
|
// submission path or a transcript.
|
||||||
type PresentationResult struct {
|
type PresentationResult struct {
|
||||||
// Output records delivery to the result destination.
|
// Output records delivery to the result destination.
|
||||||
Output DeliveryResult
|
Output DeliveryResult
|
||||||
@@ -71,6 +79,9 @@ type PresentationResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeliveryResult records rendering and writing errors for one destination.
|
// DeliveryResult records rendering and writing errors for one destination.
|
||||||
|
// The state distinguishes no submitted content, intentionally suppressed
|
||||||
|
// content, completed delivery, and incomplete delivery. RenderError and
|
||||||
|
// WriteError retain the first error of their kind for that destination.
|
||||||
type DeliveryResult struct {
|
type DeliveryResult struct {
|
||||||
// State summarizes content delivery to the destination.
|
// State summarizes content delivery to the destination.
|
||||||
State DeliveryState
|
State DeliveryState
|
||||||
@@ -80,7 +91,9 @@ type DeliveryResult struct {
|
|||||||
WriteError error
|
WriteError error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Diagnostic is passive nonterminal message data returned by a provider.
|
// Diagnostic is passive nonterminal message data returned by a provider. It
|
||||||
|
// does not emit output or select an invocation outcome; the owning integration
|
||||||
|
// submits it through the invocation reporter.
|
||||||
//
|
//
|
||||||
// Write renders the diagnostic to a supplied writer when the owning integration
|
// Write renders the diagnostic to a supplied writer when the owning integration
|
||||||
// submits it through the invocation reporter. A nil Write function has no detail.
|
// submits it through the invocation reporter. A nil Write function has no detail.
|
||||||
@@ -91,7 +104,9 @@ type Diagnostic struct {
|
|||||||
Write Detail
|
Write Detail
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquired pairs a provider value with independent diagnostics and failure context.
|
// Acquired pairs a provider value with independent diagnostics and failure
|
||||||
|
// context. The owning command chooses how to submit each diagnostic and whether
|
||||||
|
// to attach the explanation to a failed outcome.
|
||||||
type Acquired[T any] struct {
|
type Acquired[T any] struct {
|
||||||
// Value is the value returned by the acquisition callback.
|
// Value is the value returned by the acquisition callback.
|
||||||
Value T
|
Value T
|
||||||
@@ -101,11 +116,16 @@ type Acquired[T any] struct {
|
|||||||
Explanation Explanation
|
Explanation Explanation
|
||||||
}
|
}
|
||||||
|
|
||||||
// Outcome is the classified result of an operation.
|
// Outcome is the classified result of an operation. Constructing or returning
|
||||||
|
// an outcome does not itself write output; Execute presents its explanation
|
||||||
|
// during finalization.
|
||||||
//
|
//
|
||||||
// Cause records an optional operation error without selecting the outcome or
|
// Cause records an optional operation error without selecting the outcome or
|
||||||
// generating operator-facing text. Presentation records delivery observations
|
// generating operator-facing text. Presentation records delivery observations
|
||||||
// separately. Invocation coordination treats a zero Outcome as success with status 0.
|
// separately. Invocation coordination treats a zero Outcome as success with
|
||||||
|
// status 0. Presentation failures change a success or usage outcome to
|
||||||
|
// operational status 1; a domain outcome keeps its classification and nonzero
|
||||||
|
// status, while a zero domain status becomes 1.
|
||||||
type Outcome struct {
|
type Outcome struct {
|
||||||
// Kind classifies the result.
|
// Kind classifies the result.
|
||||||
Kind OutcomeKind
|
Kind OutcomeKind
|
||||||
@@ -126,28 +146,38 @@ func Success() Outcome {
|
|||||||
return Outcome{Kind: OutcomeSuccess}
|
return Outcome{Kind: OutcomeSuccess}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failure returns an operational outcome with status 1 and a terminal explanation.
|
// Failure returns an operational outcome with status 1 and a terminal
|
||||||
|
// explanation. The message and details are presented once when the outcome is
|
||||||
|
// returned from an invocation; an optional operation error can be attached with
|
||||||
|
// WithCause and is not rendered automatically.
|
||||||
func Failure(message string, details ...Detail) Outcome {
|
func Failure(message string, details ...Detail) Outcome {
|
||||||
return Outcome{Kind: OutcomeOperational, Status: 1, Explanation: Explanation{Message: message, Details: cloneDetails(details)}}
|
return Outcome{Kind: OutcomeOperational, Status: 1, Explanation: Explanation{Message: message, Details: cloneDetails(details)}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Usage returns a usage outcome with status 2 and a terminal explanation.
|
// Usage returns a usage outcome with status 2 and a terminal explanation. The
|
||||||
|
// message and details are presented when the outcome is returned from an
|
||||||
|
// invocation; an optional cause is preserved separately with WithCause.
|
||||||
func Usage(message string, details ...Detail) Outcome {
|
func Usage(message string, details ...Detail) Outcome {
|
||||||
return Outcome{Kind: OutcomeUsage, Status: 2, Explanation: Explanation{Message: message, Details: cloneDetails(details)}}
|
return Outcome{Kind: OutcomeUsage, Status: 2, Explanation: Explanation{Message: message, Details: cloneDetails(details)}}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Domain returns an application-domain outcome with the supplied name and status.
|
// Domain returns an application-domain outcome with the supplied name and
|
||||||
|
// status. The application owns the classification and status decision.
|
||||||
func Domain(name string, status int) Outcome {
|
func Domain(name string, status int) Outcome {
|
||||||
return Outcome{Kind: OutcomeDomain, Status: status, Domain: name}
|
return Outcome{Kind: OutcomeDomain, Status: status, Domain: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithExplanation returns a copy of the outcome with the supplied terminal explanation.
|
// WithExplanation returns a copy of the outcome with the supplied terminal
|
||||||
|
// explanation, replacing any existing explanation. CommandKit presents it once
|
||||||
|
// during finalization, including in quiet mode.
|
||||||
func (o Outcome) WithExplanation(message string, details ...Detail) Outcome {
|
func (o Outcome) WithExplanation(message string, details ...Detail) Outcome {
|
||||||
o.Explanation = Explanation{Message: message, Details: cloneDetails(details)}
|
o.Explanation = Explanation{Message: message, Details: cloneDetails(details)}
|
||||||
return o
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithCause returns a copy of the outcome with the supplied optional cause.
|
// WithCause returns a copy of the outcome with the supplied optional operation
|
||||||
|
// cause. The cause is preserved for caller inspection and does not select an
|
||||||
|
// outcome or generate operator-facing text.
|
||||||
func (o Outcome) WithCause(cause error) Outcome {
|
func (o Outcome) WithCause(cause error) Outcome {
|
||||||
o.Cause = cause
|
o.Cause = cause
|
||||||
return o
|
return o
|
||||||
|
|||||||
53
reporter.go
53
reporter.go
@@ -60,16 +60,24 @@ type deferredMessage struct {
|
|||||||
details []Detail
|
details []Detail
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reporter coordinates presentation and delivery for one invocation.
|
// Reporter coordinates presentation and delivery for one invocation. The
|
||||||
|
// invocation supplies it; consumers do not construct or finalize it. Reporting
|
||||||
|
// operations on one reporter are safe concurrently, although concurrent
|
||||||
|
// submissions have no predetermined order. Rendering callbacks must not
|
||||||
|
// reenter the same reporter, and their supplied writer is valid only while the
|
||||||
|
// callback runs.
|
||||||
//
|
//
|
||||||
// The invocation supplies the reporter. Consumers use Output for substantive
|
// Consumers use Output for substantive command results and the reporting
|
||||||
// command results and the reporting methods for categorized messages.
|
// methods for categorized messages. Delivery and rendering failures are
|
||||||
|
// retained for Outcome.Presentation even when a caller ignores an immediate
|
||||||
|
// method's returned error.
|
||||||
type Reporter struct {
|
type Reporter struct {
|
||||||
state *reportingState
|
state *reportingState
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeferredReporter queues messages for delivery during invocation finalization.
|
// DeferredReporter queues messages for delivery during invocation finalization.
|
||||||
// Copies share the same invocation reporting state.
|
// Copies share the same invocation reporting state. Submissions made after
|
||||||
|
// finalization return ErrReporterClosed.
|
||||||
type DeferredReporter struct {
|
type DeferredReporter struct {
|
||||||
state *reportingState
|
state *reportingState
|
||||||
}
|
}
|
||||||
@@ -126,7 +134,10 @@ func (r *Reporter) applySelection(selection commandmeta.ReportingSelection) {
|
|||||||
state.progressSet = selection.ProgressSet
|
state.progressSet = selection.ProgressSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output returns a managed writer for substantive command results.
|
// Output returns a managed writer for substantive command results. Writes are
|
||||||
|
// serialized with other operations through this reporter, and failures are
|
||||||
|
// recorded in Outcome.Presentation. The writer returns ErrReporterClosed after
|
||||||
|
// invocation finalization.
|
||||||
func (r *Reporter) Output() io.Writer {
|
func (r *Reporter) Output() io.Writer {
|
||||||
if r == nil || r.state == nil {
|
if r == nil || r.state == nil {
|
||||||
return managedOutputWriter{}
|
return managedOutputWriter{}
|
||||||
@@ -142,6 +153,10 @@ func (w managedOutputWriter) Write(p []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RenderOutput coordinates a complete substantive report rendering operation.
|
// RenderOutput coordinates a complete substantive report rendering operation.
|
||||||
|
// The callback receives a writer usable only during the callback and must not
|
||||||
|
// reenter this reporter. In quiet mode, the callback still runs against a
|
||||||
|
// discard destination so rendering failures are retained without writing to
|
||||||
|
// the caller's output destination.
|
||||||
func (r *Reporter) RenderOutput(write func(io.Writer) error) error {
|
func (r *Reporter) RenderOutput(write func(io.Writer) error) error {
|
||||||
if r == nil || r.state == nil {
|
if r == nil || r.state == nil {
|
||||||
return ErrReporterClosed
|
return ErrReporterClosed
|
||||||
@@ -168,27 +183,33 @@ func (r *Reporter) RenderOutput(write func(io.Writer) error) error {
|
|||||||
return finishRenderLocked(state, destinationOutput, renderErr, writer.writeError)
|
return finishRenderLocked(state, destinationOutput, renderErr, writer.writeError)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info submits an informational message.
|
// Info submits an informational message to the diagnostic destination. Its
|
||||||
|
// visibility follows the selected reporting mode.
|
||||||
func (r *Reporter) Info(message string, details ...Detail) error {
|
func (r *Reporter) Info(message string, details ...Detail) error {
|
||||||
return r.submitMessage(categoryInfo, message, details)
|
return r.submitMessage(categoryInfo, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn submits a warning message.
|
// Warn submits a warning message to the diagnostic destination. Its visibility
|
||||||
|
// follows the selected reporting mode.
|
||||||
func (r *Reporter) Warn(message string, details ...Detail) error {
|
func (r *Reporter) Warn(message string, details ...Detail) error {
|
||||||
return r.submitMessage(categoryWarning, message, details)
|
return r.submitMessage(categoryWarning, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug submits a debug message.
|
// Debug submits a debug message to the diagnostic destination. Its visibility
|
||||||
|
// follows the selected reporting mode.
|
||||||
func (r *Reporter) Debug(message string, details ...Detail) error {
|
func (r *Reporter) Debug(message string, details ...Detail) error {
|
||||||
return r.submitMessage(categoryDebug, message, details)
|
return r.submitMessage(categoryDebug, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Progress submits a progress message.
|
// Progress submits a progress message to the diagnostic destination. Its
|
||||||
|
// visibility follows the selected mode and explicit progress setting.
|
||||||
func (r *Reporter) Progress(message string, details ...Detail) error {
|
func (r *Reporter) Progress(message string, details ...Detail) error {
|
||||||
return r.submitMessage(categoryProgress, message, details)
|
return r.submitMessage(categoryProgress, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AtEnd returns a view for messages delivered after the handler returns.
|
// AtEnd returns a view for messages delivered after the handler returns and
|
||||||
|
// before terminal explanation delivery. The deferred view shares this
|
||||||
|
// invocation's state.
|
||||||
func (r *Reporter) AtEnd() DeferredReporter {
|
func (r *Reporter) AtEnd() DeferredReporter {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return DeferredReporter{}
|
return DeferredReporter{}
|
||||||
@@ -196,17 +217,23 @@ func (r *Reporter) AtEnd() DeferredReporter {
|
|||||||
return DeferredReporter{state: r.state}
|
return DeferredReporter{state: r.state}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info queues an informational message for invocation finalization.
|
// Info queues an informational message for invocation finalization. The
|
||||||
|
// submission error is returned immediately; rendering and delivery errors are
|
||||||
|
// reflected in the final outcome.
|
||||||
func (r DeferredReporter) Info(message string, details ...Detail) error {
|
func (r DeferredReporter) Info(message string, details ...Detail) error {
|
||||||
return r.enqueue(categoryInfo, message, details)
|
return r.enqueue(categoryInfo, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn queues a warning message for invocation finalization.
|
// Warn queues a warning message for invocation finalization. The submission
|
||||||
|
// error is returned immediately; rendering and delivery errors are reflected in
|
||||||
|
// the final outcome.
|
||||||
func (r DeferredReporter) Warn(message string, details ...Detail) error {
|
func (r DeferredReporter) Warn(message string, details ...Detail) error {
|
||||||
return r.enqueue(categoryWarning, message, details)
|
return r.enqueue(categoryWarning, message, details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug queues a debug message for invocation finalization.
|
// Debug queues a debug message for invocation finalization. The submission
|
||||||
|
// error is returned immediately; rendering and delivery errors are reflected in
|
||||||
|
// the final outcome.
|
||||||
func (r DeferredReporter) Debug(message string, details ...Detail) error {
|
func (r DeferredReporter) Debug(message string, details ...Detail) error {
|
||||||
return r.enqueue(categoryDebug, message, details)
|
return r.enqueue(categoryDebug, message, details)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user