diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md new file mode 100644 index 0000000..3823bb2 --- /dev/null +++ b/docs/roadmap/implementation.md @@ -0,0 +1,682 @@ +# Invocation reporting implementation plan + +Status: ready for implementation. No implementation stages are complete. + +## Objective and authority + +Implement the end state selected in the [reporting roadmap](reporting.md), under +[ADR 0014](../adr/0014-invocation-reporting.md), +[ADR 0005](../adr/0005-invocation-outcomes.md), and the +[architecture policy](../policy/architecture.md). The roadmap owns the selected +behavior and target API; this document owns the steps from the current code to +that end state. Read those sources before starting. + +CommandKit owns presentation, invocation coordination, and its own failures. +Applications own their domain responses and selected outcomes. ConfigKit and +PromptKit own their native semantics, diagnostic evidence, and disclosure rules. +The [testing policy](../policy/testing.md#upstream-integration-testing-ownership) +applies to every stage: test CommandKit's adaptation and presentation, without +retesting upstream functionality. + +## Sprint instructions + +- Follow the stages in order. Each stage is sized as a separate Luna task. + Read the entire plan initially and the owning roadmap sections for each stage. +- This is one end-to-end sprint. Intermediate stages need not compile or leave + the repository coherent. Reach the clean final API directly; do not introduce + compatibility constructors, duplicate submission paths, or temporary adapters + merely to make intermediate commits buildable. +- Preserve behavior outside the selected reporting changes, including command + and flag aliases, typed input semantics, provider lifetimes, scope selection, + native reports, and optional-module dependency direction. +- Inspect existing tests before adding coverage. Migrate tests whose contracts + intentionally change; retain protection for unaffected behavior. Each stage's + validation list identifies risks to protect, not a requirement for one test + per bullet or an exhaustive cross product. +- Add or revise focused tests with the owning implementation. Run executable + focused checks when their dependencies are ready. Record deferred validation + accurately; a broken intermediate build is not evidence of a passing test. + Stage 20 validates the assembled repository. +- Follow the [agent policy](../policy/agents.md), including focused local commits + and preservation of unrelated changes. Update this plan's stage status as work + completes. Do not push, tag, publish, or retire these planning documents as + part of this sprint. + +## Baseline and implementation boundaries + +At planning baseline `1d29cdd`, core handlers receive raw `Invocation.Streams`. +`Outcome` combines causes, queued diagnostics, and older delivery fields. +`execution.present` coordinates final diagnostics. The Cobra adapter returns +per-binding flag values and spellings, but not their order across different +flags. Reporting modes and an invocation reporter do not exist. + +Core remains responsible for the public reporter, outcome types, visibility, +delivery accounting, flag policy, and automatic finalization. Keep ordinary +private implementation beside the root facade where appropriate; introducing a +new public package is unnecessary. `internal/commandmeta` carries neutral parser +metadata, and `internal/cobra` continues to contain Cobra/pflag-specific code. + +`integrations/ckconfig` owns ConfigKit adaptation and configuration command +presentation. `integrations/ckprompt` owns PromptKit adaptation and commands and +may use ckconfig. Neither integration becomes a dependency of core, and ckconfig +does not import ckprompt. Providers return passive data; they do not acquire a +reporter parameter. + +Use one shared private state per reporter and serialize operations with a mutex. +Use synchronous writes rather than adding a buffering or worker subsystem. +Render callbacks receive a writer for the already-coordinated operation; that +writer must not reacquire the reporter lock. Callback reentrancy restrictions +are those selected in the roadmap, without runtime detection machinery. + +## Stage 1: Replace outcome and provider data declarations + +Status: pending. + +Primary files: [outcome.go](../../outcome.go) and their focused contract tests. + +1. Implement the exact `Explanation`, `Outcome`, `PresentationResult`, + `DeliveryResult`, and `DeliveryState` declarations selected in the roadmap. + Use the selected `uint8` delivery enumeration, including `DeliverySuppressed`. + Remove the superseded outcome diagnostic/delivery fields. +2. Implement `Success`, `Failure(message, details...)`, `Usage(message, + details...)`, `Domain(name, status)`, `WithExplanation`, and `WithCause`. + Copy accepted detail slices so replacing or modifying the caller's slice + does not change a captured callback list. Callback-captured data remains + caller-owned. Constructors and modifiers emit nothing. +3. Preserve optional `Cause` unchanged. It does not select status, category, or + explanation. Preserve zero-value outcome success without treating a cause + as a reason to infer failure. `WithExplanation` preserves cause; + `WithCause` preserves classification, status, and explanation. +4. Add `Explanation` to `Acquired[T]`. Keep `Diagnostic` as passive severity and + renderer data. Retain `SeverityWarning` and add `SeverityInfo`, + `SeverityDebug`, and `SeverityProgress`; remove `SeverityError` because + terminal content now belongs to `Explanation`. Retain `MessageDiagnostic` + as a passive literal-message renderer helper, without emitting or selecting + an outcome. +5. Declare `ErrReporterClosed` with the selected error text. Do not retain the + old API through overloaded or parallel constructors. + +Validation: protect constructor/modifier independence, copied callback lists, +non-emission, and cause identity using `errors.Is` and `errors.As`. Existing +callers are migrated in later stages. + +## Stage 2: Implement reporter state and managed output writers + +Status: pending. + +Primary files: new private reporting implementation in core, plus +[identity.go](../../identity.go) as needed for internal wiring. + +1. Add the public `Reporter` facade backed by one private invocation state. + Its private constructor accepts caller-selected destinations and starts in + ordinary mode. Keep `Streams` as the `App.Execute` input; preserve existing + nil-destination normalization. +2. Implement `Output()` using a managed `io.Writer`. Serialize each write, + preserve ordinary writer return behavior, and record the first destination + failure even if the handler ignores it. Normalize a short write with nil + error to `io.ErrShortWrite`. +3. Track result and diagnostic destinations independently. A failed destination + receives no more writes; a healthy destination remains usable. Keep the + first render error and first write error per destination, without a history + or content buffer. +4. Implement private visibility state for ordinary, quiet, verbose, and debug, + plus explicit progress value and presence. Quiet output writes discard + bytes successfully without calling the supplied destination. +5. Aggregate delivery observations according to the roadmap: incomplete when + rendering or writing failed; otherwise complete when requested delivery + completed, suppressed when all submitted content was hidden, and none when + no content was submitted. Merely obtaining an output handle submits nothing. +6. Retained output handles consult shared lifecycle state on every write. + After closure they return `ErrReporterClosed`, including under quiet mode. + Do not close or automatically flush caller-owned destinations. + +Validation: use controlled writers to cover visible and suppressed output, +short writes, ignored errors, bounded first-error retention, destination +independence, and retained-handle closure. No concurrent `App.Execute` support is +introduced by reporter synchronization. + +## Stage 3: Implement atomic rendering and categorized messages + +Status: pending. + +1. Implement `RenderOutput`, `Info`, `Warn`, `Debug`, and `Progress` with the + exact roadmap signatures. A render operation or complete categorized message + owns the reporting lock for its heading and all details. +2. Render callbacks through their supplied writer. The internal writer records + destination failures without recursively locking the reporter. Multiple raw + `Output().Write` calls remain separate operations. +3. Implement literal headings, the selected prefixes and channels, newline + termination, empty-heading behavior, and ordered details. Skip nil details. + Preserve native multiline content and distinct submissions with equal text. +4. Apply the selected visibility table and progress precedence. Suppressed rich + renderers execute against discard initially; simple hidden headings need no + formatting or destination write. Do not retain hidden content. +5. Record callback failures as presentation failures even when ignored. Distinguish + them from sink failures: a callback error alone does not mark the destination + unusable. A propagated managed-writer error is evidence of the write failure, + not a second independently discovered rendering failure; independently + returned renderer errors remain available separately. +6. Keep the directly invoked encoder boundary: an encoder called by application + code on `Output()` owns its encoding error, while managed writer errors are + still tracked. CommandKit owns callback errors from `RenderOutput` and details. + +Validation: cover category visibility and destination, prefixes, empty/native +headings, detail order, rendering failure before any write, rendering failure +under quiet mode, and independent rendering/write failures. Exercise concurrent +complete messages and rendering operations with deterministic synchronization; +assert intact operations without imposing an order among concurrent callers. + +## Stage 4: Implement deferred delivery and finalization + +Status: pending. + +1. Implement `AtEnd` and the selected value-type `DeferredReporter` methods. + Copy callback lists on submission. Queue messages in submission order, + without sorting by severity or retaining a delivered transcript. +2. Implement one private finalization path: drain eligible deferred messages; + finish ordinary reporting including the completion event supplied later; + account for failures; present the terminal explanation; close the reporter; + populate and return `Outcome.Presentation`. +3. Deferred messages remain eligible on failure. Handler Go defers run before + finalization. Applications finish reporting goroutines before returning; + this is not a task-waiting or cancellation subsystem. +4. Before terminal delivery, insert and retain `Command failed.` only for a + non-zero status with an empty heading and no non-nil detail callback. + Trust a supplied renderer even if it emits no bytes. Do not inspect its + output by buffering or replaying it. +5. Apply the selected failure table: any presentation failure changes a standard + outcome, including usage, to operational status `1`. Preserve domain name + and non-zero status; change domain status `0` to `1`. Preserve the original + explanation and optional cause, recording presentation evidence separately. +6. If presentation failure turns success into failure without an explanation, + supply a useful core-owned explanation through a healthy diagnostic + destination. Never derive application text from `Cause`, redirect failed + diagnostics into results, or recursively report a broken diagnostic sink. +7. Terminal delivery failures update observations and outcome classification + without scheduling another terminal explanation. Close every shared handle + before returning. Clear consumed deferred/parser state. + +Validation: cover immediate/deferred/terminal ordering, deferred failures, +generic fallback and retention, explicit zero-byte native explanations, +success/usage/operational/domain transitions, preserved causes and explanations, +healthy diagnostic delivery following renderer failure, and closed retained +reporter/deferred/output handles. Include failures during terminal delivery. + +## Stage 5: Install shared reporting flag metadata + +Status: pending. + +Primary files: [command.go](../../command.go), +[parser.go](../../parser.go), [flag_aliases.go](../../flag_aliases.go), +[help_view.go](../../help_view.go), and +[internal/commandmeta/metadata.go](../../internal/commandmeta/metadata.go). + +1. Define shared neutral metadata for the four long boolean flags: `quiet`, + `verbose`, `debug`, and `progress`. Supply it to every parse/help context: + root, canonical groups, runnable commands, built-ins, and alias-only discovery. + Keep Cobra/pflag declarations inside the adapter. +2. Extend reserved-name validation to those four long names. Preserve capture + error retention, installation collision reporting, and batch atomicity, + including later registration. Do not reserve unselected short spellings. +3. Include core flags among alias targets and canonical spelling collisions in + every applicable context. Applications may register their own short aliases + through the existing API; core supplies none for reporting flags. +4. Keep reporting flags separate from consumer typed bindings. Do not shift + `BindingSet` identities or change the number/order of values supplied to a + captured input preparer. +5. Extend help metadata without manufacturing canonical nodes for discovery + contexts or changing entered/canonical identity rules. + +Validation: protect installation collisions and atomicity, aliases to each core +flag, canonical-spelling collisions, unchanged typed binding indexes, and flag +availability in root/group/built-in/discovery help. + +## Stage 6: Preserve occurrence order through the normal parser + +Status: pending. + +Primary files: [internal/cobra/flags.go](../../internal/cobra/flags.go), +[internal/cobra/parse.go](../../internal/cobra/parse.go), and neutral metadata. + +1. Extend the neutral parse result with ordered flag-occurrence evidence carrying + canonical flag identity, entered spelling, and raw value. Keep existing + per-binding values and spelling information for typed inputs. +2. Record occurrences when the normal parser consumes flags, using the existing + alias interpreter and raw-value collection. Do not add a second raw-argv + scanner for verbosity. Preserve the consumed prefix when parsing fails; + do not invent occurrences after the failing token. +3. Reduce reporting occurrences in argv order. Convert every supplied boolean, + including overwritten occurrences. True selects its mode; false clears only + the currently selected matching mode to ordinary. Track the last explicit + progress value and its presence independently. +4. Ensure aliased and canonical spellings share one order, including existing + short-alias clusters and boolean syntax. Keep option-looking flag values, + operands after `--`, and ordinary consumer flag values unchanged. +5. Preserve command-path placement rules, interspersed operands after the + complete path, existing failure precedence where unaffected, and help + boolean handling. Unknown flags and invalid booleans remain usage failures. +6. Make the resolved presentation selection and relevant neutral parser events + available to core before output or input factories run. Partial selection + on failure must not affect unconditional terminal-error visibility. + +Validation: own the dense ordering cases at the parser/reducer boundary: every +roadmap reset example, mixed aliases, repeated booleans, invalid earlier values, +explicit progress before/after mode flags, values containing reporting-like +tokens, terminators, and malformed paths. Retain coverage for input spelling +provenance and consumer binding conversion. + +## Stage 7: Connect invocation execution to one reporter + +Status: pending. + +Primary files: [identity.go](../../identity.go), +[execute.go](../../execute.go), [route.go](../../route.go), +[flag_values.go](../../flag_values.go), and their invocation tests. + +1. Replace handler-facing `Invocation.Streams` with a private reporter reference + and the public `Invocation.Reporter()` method. Retain context and entered/ + canonical accessors. `App.Execute` continues accepting caller `Streams`. +2. Construct one reporter for every invocation, including paths that fail before + a handler exists. Apply parsed selection before successful output, input + preparation, providers, or the handler. +3. Replace old `present` bookkeeping with the single finalization path. Route + every normal return through it: nil application/context errors, route and + parse failures, preparation failures, group/help results, and handler outcomes. +4. Convert CommandKit-owned errors deliberately into the new message-first + constructors, preserving applicable cause identity with `WithCause`. + Preserve `ErrFlagInput`/`ErrFlagWiring` classification and input validation. + Do not use a generic rule that turns any application cause into terminal text. +5. Attach usage guidance as terminal explanation detail, visible under quiet. + Preserve entered alias paths, custom discovery usage, and the distinction + between unresolved routes and canonical command identity. +6. Populate presentation observations from actual reporter state rather than + accepting handler-supplied observation fields as delivery evidence. + Preserve fresh input/state lifetimes and registration from handlers; a + refreshed registry snapshot must not replace the invocation's reporter. + +Validation: exercise early failures, handler success and domain outcomes, +cleanup writes, ignored writer failures, repeated invocations, alias identity, +and usage guidance in quiet. Preserve factory-free help/preflight behavior and +existing input conversion/cause tests under the new API. + +## Stage 8: Migrate help and version presentation + +Status: pending. + +Primary files: [builtins.go](../../builtins.go), help metadata/rendering, +and built-in consumer tests. + +1. Route successful help and version results through substantive reporting. + Quiet success emits neither report nor a terminal explanation. +2. Keep help-path validation and invalid component/version selection as usage + handling. An unknown help target must not become a rendering failure merely + because help uses `RenderOutput` for presentation. +3. Put actual help/version rendering and delivery under managed reporting, + using the supplied callback writer. Preserve the internal backend boundary + and discovery help metadata. Render quietly into discard where required. +4. Keep application version as the default and existing explicit component + selection intact. Do not add new version scopes or dependency inspection. +5. Remove built-in paths that write directly to invocation streams or manually + populate superseded incomplete-report fields. + +Validation: cover `help --quiet`, `version --quiet`, canonical and alias help, +alias-only discovery, shared reporting flags, invalid help/version requests, +factory-free behavior, and help/version destination failures. Invalid requests +remain usage outcomes unless presentation subsequently fails. + +## Stage 9: Add core debug events + +Status: pending. + +1. Instrument routing, command-alias resolution, verbosity selection, and handler + completion. Explain the relevant entered/canonical paths and decisions. + Include flag-alias identity when it explains reporting selection. +2. Collect early routing/parser events temporarily and submit them only after + final mode selection. Clear them after submission; do not add a transcript. +3. Submit the completion event after the handler returns and after deferred + messages, before terminal presentation. Describe the handler's classification + and status; the returned outcome remains authoritative after delivery. +4. Use shared Debug reporting for events and normal presentation failure handling + for their delivery. Do not dump argv values, configuration values, causes, or + provider objects. Installation errors remain ordinary returned Go errors. +5. Other candidate events in the roadmap are opportunities, not mandatory + instrumentation for every internal step. Do not turn supported repetition + into a warning. + +Validation: `--verbose --debug` reveals earlier selection events; +`--debug --quiet` hides them. Cover alias paths, completion before terminal +explanation, absence of completion when no handler runs, and debug delivery +failure. Assert selected meaning and order rather than incidental prose. + +## Stage 10: Separate ConfigKit provider messages and explanations + +Status: pending. + +Primary files: +[configkit_adapter.go](../../integrations/ckconfig/configkit_adapter.go), +[contracts.go](../../integrations/ckconfig/contracts.go), and adapter tests. + +1. Migrate `FromConfigKit`, comparison acquisition, and diagnostic helpers to + `Acquired.Diagnostics` plus `Acquired.Explanation`. Public provider callbacks + remain passive and retain their existing context/request/input/state shape. +2. Replace highest-severity whole-batch promotion. Partition native records into + independent nonterminal messages and identified terminal context. Native + error records belong to the explanation; independent warnings remain warnings. + Preserve explicitly related native context with its owning record. +3. Preserve native diagnostic writers, source identifiers/legends, selected + scope and comparison-side context, safe disclosure, and record order within + each resulting presentation path. Snapshot renderer inputs as needed for + deferred use; do not infer relationships from text or error-chain wording. +4. Preserve data returned alongside errors and supported Go error identity. + A native terminal explanation must not also be submitted as an independent + diagnostic or repeated through a generic cause-derived message. +5. Preserve comparison left/right preparation and failure behavior. Carry + already-acquired independent messages through a later acquisition failure. + +Validation: adapter tests establish faithful record separation, source/side +context, passive acquisition, retained causes, and data alongside errors. +Use native results as fixtures without testing ConfigKit's resolution or +diagnostic classification algorithms. + +## Stage 11: Migrate configuration show and validate + +Status: pending. + +Primary files: [show.go](../../integrations/ckconfig/show.go), +[validate.go](../../integrations/ckconfig/validate.go), and +[operations.go](../../integrations/ckconfig/operations.go). + +1. Introduce small integration-private helpers to submit passive diagnostics to + the corresponding reporter methods, using the deferred view for end-of-run + warnings/context. Native fully formatted renderers use empty headings. + Progress, if present, is immediate; no deferred Progress API is added. +2. Replace old `configOperationFailure`/incomplete-report bookkeeping with explicit + explanations, optional original causes, and reporter-owned delivery evidence. + Use an acquired native explanation when available; otherwise select a useful + integration-owned operation explanation. Do not add a second cause printout. +3. Migrate `config show` to managed rendering. Preserve loading all selected + views before any report output, single-scope native YAML, and ordered + `--scope all` framing, including existing directive/document handling. + Keep necessary per-document buffers; do not introduce whole-run buffering. +4. Include serialization, native rendering, and framing inside the managed + rendering operation so callback failures are recorded under quiet as well. + Report additional messages outside callbacks through the reporter. +5. Migrate `config validate`, including selected-scope iteration, result records, + acquisition failure, and terminal explanation. Preserve existing request and + invocation-state lifetimes, cancellation, and preflight selection. + +Validation: preserve show YAML/framing and load-before-output protections. +Add representative mixed warning/failure visibility in ordinary/verbose/quiet, +deferred context ordering, rendering failures, and report write failures. +Update tests of superseded outcome fields to observable reports and +`Presentation`, rather than dropping their original failure protection. + +## Stage 12: Migrate configuration sources, explain, and diff + +Status: pending. + +Primary files: [sources.go](../../integrations/ckconfig/sources.go), +[explain.go](../../integrations/ckconfig/explain.go), +[diff.go](../../integrations/ckconfig/diff.go), and remaining report helpers. + +1. Migrate remaining commands to the same reporting helpers and deliberate + operation explanations. Preserve scope availability, selection, source + evidence, redaction, and ConfigKit-owned comparison semantics. +2. Wrap the complete CommandKit-owned report rendering in `RenderOutput`, + including preparation/encoding that can fail before destination writes. + Keep existing safe diff YAML and changed/deleted-field presentation. +3. Submit independent provider messages once and attach terminal explanation + only to the returned failed outcome. Preserve partial results already + delivered according to each command's existing behavior. +4. Remove obsolete integration delivery flags, outcome diagnostic attachment, + manual writer tracking, and helpers superseded by the shared reporter. + Preserve meaningful operation causes; do not assign a presentation error as + the operation cause merely to reproduce old bookkeeping. + +Validation: retain comparison preflight, selector, safe-report, and native +forwarding tests. Cover a representative failure on each destination and quiet +rendering without duplicating core's complete visibility matrix in every command. + +## Stage 13: Migrate PromptKit acquisition adapters + +Status: pending. + +Primary files: [adapters.go](../../integrations/ckprompt/adapters.go), +[validation.go](../../integrations/ckprompt/validation.go), +[smoke.go](../../integrations/ckprompt/smoke.go), and provider contracts. + +1. Carry passive independent diagnostics and terminal explanation separately + through engine loading, definition/requirements acquisition, request + validation, and smoke acquisition. Use a private acquisition bundle where + necessary to avoid losing either field between helpers. +2. Replace mixed-batch severity promotion while preserving native rendering, + primary/related source context, source legends, scope/side labels, and + disclosure. Keep unrelated warnings out of terminal explanations. +3. Update `ConfigScope` and engine comparison to use the migrated ckconfig + contracts. Keep dependency direction ckprompt to ckconfig. +4. Preserve original returned errors, useful reports alongside errors, native + validation/smoke evidence, builder/preflight order, and selected request + lifetimes. Providers remain independent of the reporter. +5. Use upstream APIs as adopted. Do not add probes, diagnostic interpretation, + extra inference calls, capability warnings, or newly required configuration. + +Validation: establish correct forwarding, passive data, separated context, +and supported error identity. Preserve offline fixtures and existing builder/ +acquisition lifecycle protections. No live provider or credentials are needed. + +## Stage 14: Migrate PromptKit listing and inspection commands + +Status: pending. + +Primary file: [command.go](../../integrations/ckprompt/command.go) and its +catalog, definition, and requirements report helpers/tests. + +1. Migrate catalog listing, definition inspection, and requirements inspection + to the reporter, replacing raw stream writes and old `definitionFailure` + diagnostic bookkeeping. +2. Submit independent diagnostics once through small integration-private + category helpers; use acquired terminal context on failure and preserve + optional original causes. Native labelled detail uses an empty heading. +3. Enclose report preparation, native rendering/encoding, and delivery in + managed rendering where CommandKit invokes them. Quiet runs still discover + report-generation failures without touching caller result destinations. +4. Preserve native optional/version fields, text/YAML formats, selection, + aliases, request bindings, and command availability. The reporting feature + does not change what an inspection means or which APIs it invokes. + +Validation: migrate existing report/selection tests; add representative +successful quiet/verbose/debug execution and native acquisition failure with an +independent warning. Reuse core reporting coverage for universal mechanics. + +## Stage 15: Migrate request validation and smoke commands + +Status: pending. + +Primary files: +[validation_command.go](../../integrations/ckprompt/validation_command.go) and +[smoke_command.go](../../integrations/ckprompt/smoke_command.go). + +1. Migrate concrete requirements validation to managed output, passive-message + submission, explicit terminal explanation, and optional cause transport. + Preserve its native report and established status decisions. +2. Migrate each `promptkit test` command and `test all`. Keep the established + four-test order, aggregate request/state reuse, continuation/stop behavior, + cancellation, and operation-error handling except for selected shared + presentation changes. +3. Preserve a substantive smoke report returned alongside an operation error. + Render it before finalization, then attach the terminal explanation. Under + quiet, render into discard while retaining terminal failure visibility. +4. Preserve aggregate collection before its single report is encoded and + submitted. Move aggregate encoding and writing into managed rendering; + do not introduce per-test streaming or change which native tests run because + presentation now uses a reporter. Replace old `smokeDeliveryFailure` flags + with reporter evidence, preserving operation causes and explanations + independently of presentation failures. +5. Remove obsolete manually tracked delivery state. Do not reinterpret native + supported/completed/result fields or add unsolicited warnings. + +Validation: use offline stubs/native fixtures to protect aggregate order and +bindings, reports alongside errors, diagnostic ordering, cancellation, +render/write failures, and quiet semantics. Test CommandKit coordination, +not whether PromptKit's validation or smoke checks implement their domain rules. + +## Stage 16: Maintain a core reporting consumer + +Status: pending. + +Primary files: [examples/core/main.go](../../examples/core/main.go) and its +existing example tests. + +1. Migrate current custom commands to `Invocation.Reporter()` while preserving + their existing input and alias demonstrations. +2. Add one small application-owned reporting demonstration to this existing + example, using deterministic local operations/fixtures. Demonstrate ordinary + result rendering, optional Warning and Info, Progress, Debug, and a deferred + summary. Avoid adding another module or an external service. +3. Provide simple selectable scenarios for silent recovery, an explicit warning + with/without a Go error, and a terminal explanation without a cause. Include + failure after partial output and optional cause transport independent of text. +4. Show rendering helpers using their supplied callback writer and additional + message submissions outside callbacks. Keep examples focused on public usage; + delivery accounting mechanics belong in tests/internal documentation. + +Validation: keep the example runnable offline and cover representative modes +and failure paths with its owning suite. Use package tests for detailed cause +identity and delivery states rather than expanding the example into a framework. + +## Stage 17: Migrate maintained integration consumers + +Status: pending. + +Primary directories: +[ckconfig example](../../integrations/ckconfig/examples/simple) and +[composed PromptKit example](../../integrations/ckprompt/examples/composed). + +1. Migrate custom handlers and provider diagnostics to the selected APIs. + Preserve composition, aliases, configuration scopes, input/state sharing, + and the offline smoke client/fixtures. +2. Ensure examples demonstrate independent provider warnings separately from + native terminal context where applicable. Do not add artificial upstream + capabilities merely to produce every message category. +3. Adapt their existing tests to reporters and presentation observations while + retaining native YAML, discovery, and custom-command behavior protections. +4. Exercise ordinary/quiet configuration output, a verbose provider warning, + aliased help, and a smoke report plus terminal failure using controlled + fixture evidence. Avoid multiplying identical mode cases across all commands. + +Validation: both example packages compile in their owning modules and run +without external services. Confirm custom commands and integration commands +share the same reporting flags and terminal behavior. + +## Stage 18: Reconcile the full test suite and architectural boundaries + +Status: pending. + +1. Find and migrate remaining callers of removed constructors, raw invocation + streams, terminal `SeverityError`, outcome diagnostic submission, and old + delivery fields across tests, benchmarks, and supporting code. `Streams` + supplied to `Execute` remains valid; passive provider diagnostics remain valid. +2. Preserve regression coverage for alias routing, discovery, installation + atomicity, typed presence/false/zero values, invocation freshness, help without + loading, native report contracts, cancellation, and supported error identity. + Update expectations only where the selected reporting behavior changes them. +3. Consolidate reporting coverage at its owning boundary. Include all selected + delivery states, first-error retention per destination, ignored immediate + failures, deferred/terminal failures, domain status handling, caller-writer + ownership, late handles in quiet, and healthy sinks after renderer failure. +4. Verify reporter operations are safe concurrently and keep complete messages/ + callbacks intact. Use coordination primitives rather than sleeps or assumed + scheduling. Do not test recursive reporter callbacks as supported use or + infer concurrent dispatcher support. +5. Extend existing facade/import-boundary checks as needed: all new public types + belong to core, public signatures contain no Cobra/pflag/internal types, + backend imports remain internal, and optional dependencies remain optional. +6. Remove obsolete production helpers only after their responsibilities are + accounted for. Do not retain parallel delivery paths for historical tests. + +Validation: the suite should now build as a whole using the local three-module +workspace. Focused reporter race testing is justified by the selected concurrent +reporter contract; it does not establish a new permanent repository-wide gate. + +## Stage 19: Update canonical documentation and compatibility guidance + +Status: pending. + +1. Update public Go declarations/GoDoc for exact reporter, outcome, provider, + lifecycle, cause, and presentation-observation contracts. Describe callback + writer scope and the selected non-reentrant callback boundary. +2. Update [CLI reference](../cli.md) with the implemented mode/progress policy, + flag placement and aliases, prefixes/channels, quiet help/version, usage + guidance, and presentation-failure status behavior. Keep full operator + definitions here rather than duplicating them in consumer prose. +3. Update [consumer guide](../consumers/guide.md), [README](../../README.md), + integration package documentation, and [developer guide](../development.md) + as affected. Link to maintained examples; explain migration from raw + invocation streams, error-first constructors, outcome diagnostics, terminal + provider diagnostics, and old delivery fields. +4. Update [internal overview](../internal/overview.md) with implemented ownership, + parse occurrence flow, visibility selection, and finalization. Describe + synchronization as implementation mechanics without expanding contracts. +5. Update the unpublished [core v0.3.0 note](../releases/v0.3.0.md) with reporting + scope and the intentional API/CLI compatibility impact, including newly + reserved flag names. Preserve published historical notes and tags. Integration + release-version selection and publication remain separate release preparation; + do not invent release versions or edit historical integration notes. +6. Mark feature implementation status accurately in the roadmap. Preserve the + accepted ADRs and deferred work; do not create new architectural decisions + for settled API details or retire the planning record during implementation. + +Validation: review prose against implemented behavior, check local links and +fragments, and run the Markdown whitespace checks from the developer guide. +Current contract documentation must no longer present the removed APIs as valid. + +## Stage 20: Validate the complete end state and finish + +Status: pending. + +1. Format changed Go files with `gofmt`; review the complete diff for unintended + behavior changes, unselected restrictions, compatibility machinery, public + backend leakage, or duplicate presentation paths. +2. Preserve the existing ignored local `go.work`. Ensure it includes core, + ckconfig, and ckprompt using the developer guide procedure. Keep unpublished + sibling code under local workspace resolution. Do not commit workspace files, + fabricate dependency sums, or change dependency versions solely to make an + unreleased core API resolve through published versions. +3. Run the ordinary suites for all three modules with `GOTOOLCHAIN=local`, using + the workspace for integration development. The commands below are separate + executions with the indicated working directories: + + | Working directory | Command | + | --- | --- | + | Repository root | `GOTOOLCHAIN=local go test ./...` | + | `integrations/ckconfig` | `GOTOOLCHAIN=local go test ./...` | + | `integrations/ckprompt` | `GOTOOLCHAIN=local go test ./...` | + | Repository root | `GOWORK=off GOTOOLCHAIN=local go test ./...` | + +4. Run focused core reporter tests with the race detector, choosing `-run` to + match the tests created during the sprint. Exercise maintained example + commands covering core result/messaging, quiet help/version, scoped config + YAML, aliases, and offline PromptKit report-plus-failure presentation. +5. Treat workspace-based integration validation accurately: it validates this + sprint's local modules. Independent integration dependency graphs are updated + and validated during release preparation after their new dependencies are + published, following the existing core → ckconfig → ckprompt release order. + No release-tool publication exercise, remote push, or new toolchain/dependency + upgrade is part of this feature validation. +6. Check that every selected roadmap behavior is implemented or has a clearly + identified blocker. Resolve sprint defects before declaring completion. + Keep incidental debug wording, concurrent scheduling order, and private file + layout out of contractual assertions. +7. Review staged/untracked contents, local links, and `git diff --check` plus + `git diff --cached --check`. Finish with focused local commits and report + validation results, any genuine limitations, and worktree status. Do not + declare a release or remove the roadmap/plan automatically. + +## Completion criteria + +The sprint is complete when the selected public API replaces the old paths; +normal parsing supplies reporting selection in every context; one reporter owns +each invocation's presentation and finalization; core and optional integrations +share that policy; native upstream evidence remains authoritative; maintained +examples and current documentation use the implemented API; and complete local +validation succeeds. No additional product decisions are required for this plan. diff --git a/docs/roadmap/reporting.md b/docs/roadmap/reporting.md index afa3e37..1acce3f 100644 --- a/docs/roadmap/reporting.md +++ b/docs/roadmap/reporting.md @@ -13,6 +13,8 @@ below are also selected. Architectural preparation is complete: [ADR 0014](../adr/0014-invocation-reporting.md) is accepted, and the [architecture policy](../policy/architecture.md) is aligned. Implementation has not started; implementation, validation, and maintained consumer examples remain. +The [implementation plan](implementation.md) owns stage order and execution +instructions. ## Purpose @@ -850,85 +852,30 @@ Debug output follows the same upstream disclosure and safe-rendering contracts. Enabling debug does not authorize secret disclosure or bypass owning-library rules. -## Work needed +## Delivery scope -1. Specify the selected behavior in examples covering ordinary application output, - immediate and deferred diagnostics, failure after partial output, help and - version, and integration diagnostics in every mode. Include applications that - emit no Progress messages and the distinction between Info and Progress. - Cover silent recovery, an explicit Warning with or without a Go error, and a - terminal failure with an explicit explanation and no Go error cause. - Include simple and structured failure construction without early emission, - optional cause transport independent of operator text, and an integration - 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 - writer ownership to identify the smallest shared changes. Include invocation - failures that occur before a handler receives its `Invocation`. -3. Implement the selected unified reporting API and flag contracts, including - interactions with command and flag aliases, following OD-1 through OD-4 above. - Replace split handler submission paths and adapt core and integration callers. - Account for flag collisions and document changed public contracts. -4. Implement the selected behavior across core and the integrations. Preserve - 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, - ordering, duplicate prevention, terminal Error/non-zero-outcome consistency, debug - visibility, and write-failure handling with focused behavioral tests and - maintained consumer examples. Cover mode resets, mixed canonical/alias - ordering, help and discovery contexts, and core parser events presented - according to the final mode. Cover explicit progress overrides, debug's - progress default, quiet suppression, progress aliases, message prefixes, - and preservation of native multiline diagnostics. Cover explicit explanatory - context in quiet mode, independent warnings in mixed batches, already-labelled - native content, and distinct submissions with identical text. Verify the end - of normal reporting after terminal error presentation, including deferred - and late writes under the selected OD-4 behavior. Cover immediate and deferred - ordering on success and failure, handler cleanup, automatic finalization, - flushing ordinary buffers before terminal delivery, handler-completion debug - placement, and ownership of caller-supplied writers. Verify concurrent reporter - calls protect shared state and keep individual messages together, without - requiring a predetermined order among concurrent submissions. Verify ignored - immediate write errors and deferred delivery failures follow the outcome table - above, original explanations and causes are retained, and failed destinations - receive no further writes. Cover diagnostic-destination failure without - fallback into substantive output, quiet-mode rendering failures, and - suppression without destination writes or incomplete-delivery status. - Distinguish renderer failures from destination failures, including callbacks - that fail without writing and continued terminal delivery through a healthy - diagnostic destination. Cover usage failure becoming operational failure when - presentation fails, domain classification and non-zero status preservation, - and zero domain status becoming `1`. Verify all category destinations and - usage guidance under quiet mode. - Verify the selected API's empty-heading native rendering, ordered details, - deferred submission errors, replacement by `WithExplanation`, and delivery - states for each destination. Check bounded first-error observations, rendering - through `RenderOutput`, and `ErrReporterClosed` for retained handles in quiet mode. - Verify `WithCause` preserves classification, status, and explanation, and - `WithExplanation` preserves the cause. Check cause identity through outcome - processing and subsequent presentation failures, including wrapped errors - inspected with `errors.Is` and `errors.As`. Verify causes alone do not produce - 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 - when implemented. Exact reporting APIs and flag syntax remain API/CLI - contracts. +The completed feature includes the selected reporter and outcome API, ordered +mode/progress selection through normal parsing, shared core presentation, and +both optional integration migrations. Passive provider diagnostics distinguish +independent messages from terminal explanations while preserving native evidence +and rendering. Existing command behavior remains unchanged outside the selected +reporting policy. + +Maintained consumers demonstrate ordinary output, immediate/deferred messages, +silent recovery, explicit warnings, failure after partial output, optional cause +transport, and structured terminal explanations. Integration consumers include +native diagnostic context and useful reports returned alongside failures. + +Behavioral coverage establishes CommandKit-owned parsing, visibility, ordering, +concurrent reporter coordination, closure, presentation observations, and failure +handling. It preserves existing alias, input/state, discovery, native-report, +and upstream-adapter protections without testing upstream domain correctness. +GoDoc, CLI documentation, consumer guidance, internal documentation, and release +notes describe the implemented boundary under their canonical ownership. + +The [implementation plan](implementation.md) defines the concrete migration +steps, focused validation, and completion criteria. This roadmap defines the +target behavior and selected policy choices. ## Architectural preparation completed @@ -939,5 +886,6 @@ rules. ownership model, including application ownership of domain-specific error decisions and scope for useful shared error helpers. -OD-1 through OD-4 and the consumer API signatures are selected. Turn the target-API -examples into maintained, executable consumers as implementation proceeds. +OD-1 through OD-4 and the consumer API signatures are selected. The target end +state includes maintained, executable consumers using those APIs; the +[implementation plan](implementation.md) owns their delivery sequence.