Clarify provider diagnostics and reporting edge cases
This commit is contained in:
@@ -7,8 +7,9 @@ OD-2's unified reporting direction, the terminal failure model, and application
|
|||||||
ownership of domain-specific error decisions are selected.
|
ownership of domain-specific error decisions are selected.
|
||||||
OD-3's failure presentation and retention boundaries are selected.
|
OD-3's failure presentation and retention boundaries are selected.
|
||||||
OD-4's delivery lifecycle, write-failure handling, and quiet-mode rendering are
|
OD-4's delivery lifecycle, write-failure handling, and quiet-mode rendering are
|
||||||
selected. The consumer API signatures and presentation-result model below are
|
selected. The consumer API signatures, presentation-result model, provider
|
||||||
also selected. Architectural preparation is complete:
|
diagnostic boundary, fallback explanations, and rendering callback boundary
|
||||||
|
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.
|
not started; implementation, validation, and maintained consumer examples remain.
|
||||||
@@ -167,6 +168,8 @@ such as "Unable to export the requested report." The application can choose to
|
|||||||
include detail from a Go error in that explanation. CommandKit presents the
|
include detail from a Go error in that explanation. CommandKit presents the
|
||||||
supplied explanation without automatically deriving text from an application
|
supplied explanation without automatically deriving text from an application
|
||||||
error. The selected API below provides failure constructors for this purpose.
|
error. The selected API below provides failure constructors for this purpose.
|
||||||
|
When a failed outcome supplies no explanation, CommandKit supplies the generic
|
||||||
|
fallback defined under terminal outcomes below.
|
||||||
|
|
||||||
Output streamed before the failure remains visible according to its selected
|
Output streamed before the failure remains visible according to its selected
|
||||||
mode; terminal failure does not withdraw earlier bytes. Deferred messages,
|
mode; terminal failure does not withdraw earlier bytes. Deferred messages,
|
||||||
@@ -544,6 +547,21 @@ reporter operations from interleaving with it. Rendering callbacks write through
|
|||||||
their supplied writer. Each complete categorized message, including its details,
|
their supplied writer. Each complete categorized message, including its details,
|
||||||
is likewise coordinated as one reporter operation.
|
is likewise coordinated as one reporter operation.
|
||||||
|
|
||||||
|
Rendering callbacks use their supplied writer only during the callback. They may
|
||||||
|
call rendering helpers that write through it. While a callback is running, it
|
||||||
|
must not recursively submit messages, queue deferred messages, start another
|
||||||
|
rendering operation, or write through a separate `Output()` handle belonging to
|
||||||
|
the same invocation's reporter. Make additional reporter submissions before or
|
||||||
|
after the callback. A callback must also avoid waiting for another goroutine to
|
||||||
|
submit through that reporter, since the submission may be waiting for the
|
||||||
|
callback to finish.
|
||||||
|
|
||||||
|
This boundary applies to `RenderOutput`, immediate and deferred message details,
|
||||||
|
and terminal explanation details. Ordinary concurrent reporter calls remain
|
||||||
|
supported and serialized. Keeping each rendering operation together motivates
|
||||||
|
the boundary; it does not prescribe a lock implementation or promise runtime
|
||||||
|
detection of recursive calls.
|
||||||
|
|
||||||
Message strings are literal; consumers use `fmt.Sprintf` when formatting is
|
Message strings are literal; consumers use `fmt.Sprintf` when formatting is
|
||||||
needed. Initially omit parallel `Infof`, `Warnf`, and similar methods. CommandKit
|
needed. Initially omit parallel `Infof`, `Warnf`, and similar methods. CommandKit
|
||||||
formats the opening message with its category's prefix and a terminating newline.
|
formats the opening message with its category's prefix and a terminating newline.
|
||||||
@@ -651,6 +669,26 @@ The named renderers above have signature `func(io.Writer) error` and preserve th
|
|||||||
owning library's safe diagnostic formatting. They run during terminal delivery,
|
owning library's safe diagnostic formatting. They run during terminal delivery,
|
||||||
not when constructing the outcome.
|
not when constructing the outcome.
|
||||||
|
|
||||||
|
Before terminal delivery, supply the explanation `Command failed.` when a
|
||||||
|
non-zero outcome has an empty `Explanation.Message` and no non-nil callback in
|
||||||
|
`Explanation.Details`. This produces `ERROR: Command failed.` in every mode,
|
||||||
|
including quiet, and becomes the explanation retained in the returned outcome.
|
||||||
|
Adding the fallback leaves classification, status, and cause unchanged;
|
||||||
|
presentation failures still follow OD-4's rules. The fallback is based on the
|
||||||
|
failed outcome and absent explanation, without deriving text from `Cause.Error()`.
|
||||||
|
|
||||||
|
An empty heading with a non-nil detail renderer is an explicitly supplied
|
||||||
|
explanation. Trust that renderer to provide its content. Do not buffer or replay
|
||||||
|
it to decide whether the explanation is sufficiently informative, and do not
|
||||||
|
add the fallback merely because it writes no bytes.
|
||||||
|
|
||||||
|
| Returned outcome | Terminal presentation |
|
||||||
|
| --- | --- |
|
||||||
|
| `Failure("")` | Generic fallback, operational classification and status `1`. |
|
||||||
|
| `Domain("validation", 3)` | Generic fallback, domain classification and status `3`. |
|
||||||
|
| `Failure("").WithCause(err)` | Generic fallback; the supplied cause remains available without automatic rendering. |
|
||||||
|
| `Failure("", writeNativeFailure)` | Native explanation without an added generic heading. |
|
||||||
|
|
||||||
`Cause` is optional. `WithCause` returns a modified outcome value, replacing the
|
`Cause` is optional. `WithCause` returns a modified outcome value, replacing the
|
||||||
cause without changing the classification, status, or explanation. For example:
|
cause without changing the classification, status, or explanation. For example:
|
||||||
|
|
||||||
@@ -672,6 +710,42 @@ failures are recorded separately in `Presentation`. The returned outcome retains
|
|||||||
its terminal explanation and optional cause, with other retention limited to the
|
its terminal explanation and optional cause, with other retention limited to the
|
||||||
presentation needs described above.
|
presentation needs described above.
|
||||||
|
|
||||||
|
### Provider-returned diagnostic data
|
||||||
|
|
||||||
|
Providers return values and diagnostic data without needing a reporter parameter.
|
||||||
|
Retain `Acquired[T]` with separate fields for independent messages and failure
|
||||||
|
explanations:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type Acquired[T any] struct {
|
||||||
|
Value T
|
||||||
|
Diagnostics []Diagnostic
|
||||||
|
Explanation Explanation
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`Diagnostics` carries independent, nonterminal messages. `Diagnostic` and
|
||||||
|
`Severity` remain passive data types for those messages, with each diagnostic
|
||||||
|
carrying its `Severity` and a `Write func(io.Writer) error` renderer. Adapt their
|
||||||
|
contracts to the nonterminal reporting categories. Integrations submit the
|
||||||
|
records through the corresponding reporter methods, including the deferred view
|
||||||
|
where appropriate. Removing `Outcome.Diagnostics` removes a submission path;
|
||||||
|
provider-returned records remain available for the integration to submit.
|
||||||
|
|
||||||
|
`Explanation` carries context to attach when the integration returns a failed
|
||||||
|
outcome. Terminal Error content uses this field rather than an independently
|
||||||
|
submitted diagnostic. An upstream warning that helps explain the failure may
|
||||||
|
belong in the explanation; unrelated warnings remain in `Diagnostics` and follow
|
||||||
|
their ordinary visibility rules. Adapters preserve this distinction and useful
|
||||||
|
native formatting when translating mixed upstream batches, instead of assigning
|
||||||
|
the whole batch its highest severity.
|
||||||
|
|
||||||
|
Providers may return acquired data alongside a Go error. The owning integration
|
||||||
|
chooses the command outcome, attaches any terminal explanation, and decides which
|
||||||
|
cause to preserve. Returning diagnostic data does not itself emit messages or
|
||||||
|
select the invocation outcome. Diagnostic renderers follow the same callback
|
||||||
|
boundary as other details when invoked through the reporter.
|
||||||
|
|
||||||
### Presentation observations and closed reporters
|
### Presentation observations and closed reporters
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -786,7 +860,9 @@ rules.
|
|||||||
terminal failure with an explicit explanation and no Go error cause.
|
terminal failure with an explicit explanation and no Go error cause.
|
||||||
Include simple and structured failure construction without early emission,
|
Include simple and structured failure construction without early emission,
|
||||||
optional cause transport independent of operator text, and an integration
|
optional cause transport independent of operator text, and an integration
|
||||||
returning both a substantive report and a failure.
|
returning both a substantive report and a failure. Include provider-returned
|
||||||
|
independent warnings and terminal context, unexplained failures receiving the
|
||||||
|
fallback, and rendering helpers using only the supplied callback writer.
|
||||||
2. Review current diagnostic batching, parsing, help, outcome presentation, and
|
2. Review current diagnostic batching, parsing, help, outcome presentation, and
|
||||||
writer ownership to identify the smallest shared changes. Include invocation
|
writer ownership to identify the smallest shared changes. Include invocation
|
||||||
failures that occur before a handler receives its `Invocation`.
|
failures that occur before a handler receives its `Invocation`.
|
||||||
@@ -796,6 +872,10 @@ rules.
|
|||||||
Account for flag collisions and document changed public contracts.
|
Account for flag collisions and document changed public contracts.
|
||||||
4. Implement the selected behavior across core and the integrations. Preserve
|
4. Implement the selected behavior across core and the integrations. Preserve
|
||||||
upstream rendering and semantics while applying the chosen visibility policy.
|
upstream rendering and semantics while applying the chosen visibility policy.
|
||||||
|
Adapt provider-returned `Acquired[T]`, `Diagnostic`, and `Severity` contracts
|
||||||
|
to independent nonterminal messages and separate terminal explanations.
|
||||||
|
Replace whole-batch severity promotion with deliberate separation of failure
|
||||||
|
context and unrelated messages. Providers remain independent of the reporter.
|
||||||
5. Verify classification, flag selection, suppression, terminal explanations,
|
5. Verify classification, flag selection, suppression, terminal explanations,
|
||||||
ordering, duplicate prevention, terminal Error/non-zero-outcome consistency, debug
|
ordering, duplicate prevention, terminal Error/non-zero-outcome consistency, debug
|
||||||
visibility, and write-failure handling with focused behavioral tests and
|
visibility, and write-failure handling with focused behavioral tests and
|
||||||
@@ -833,6 +913,19 @@ rules.
|
|||||||
processing and subsequent presentation failures, including wrapped errors
|
processing and subsequent presentation failures, including wrapped errors
|
||||||
inspected with `errors.Is` and `errors.As`. Verify causes alone do not produce
|
inspected with `errors.Is` and `errors.As`. Verify causes alone do not produce
|
||||||
messages or change statuses or visibility.
|
messages or change statuses or visibility.
|
||||||
|
Verify provider-returned data remains unpresented until submitted by the
|
||||||
|
integration, including data returned alongside an error. Cover mixed batches
|
||||||
|
where terminal context remains visible in quiet mode and unrelated warnings
|
||||||
|
remain suppressed. Verify generic fallback presentation and retention for
|
||||||
|
failed outcomes with no message or non-nil detail renderer, with and without
|
||||||
|
a cause. Check unchanged classifications, statuses, and causes when fallback
|
||||||
|
delivery succeeds, and existing presentation-failure rules when it fails.
|
||||||
|
Cover native details with an empty heading, including a renderer that writes
|
||||||
|
no bytes, without adding a fallback or replaying callbacks to inspect content.
|
||||||
|
Exercise callback helpers using the supplied writer, messages submitted before
|
||||||
|
and after rendering, and ordinary concurrent submissions serialized around a
|
||||||
|
complete rendering operation. Document the callback boundary without requiring
|
||||||
|
runtime detection of recursive reporter use.
|
||||||
6. Update GoDoc, the CLI reference, consumer guidance, and release documentation
|
6. Update GoDoc, the CLI reference, consumer guidance, and release documentation
|
||||||
when implemented. Exact reporting APIs and flag syntax remain API/CLI
|
when implemented. Exact reporting APIs and flag syntax remain API/CLI
|
||||||
contracts.
|
contracts.
|
||||||
|
|||||||
Reference in New Issue
Block a user