From 10a799a2b7457e53e38010c141e45b7635070ef6 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Tue, 3 Nov 2026 03:32:18 +0000 Subject: [PATCH] Plan shell completion implementation --- docs/roadmap/completion.md | 187 ++++++ docs/roadmap/deferred.md | 18 +- docs/roadmap/implementation.md | 1058 +++++++------------------------- docs/roadmap/remediation.md | 4 +- docs/roadmap/reporting.md | 6 +- 5 files changed, 447 insertions(+), 826 deletions(-) create mode 100644 docs/roadmap/completion.md diff --git a/docs/roadmap/completion.md b/docs/roadmap/completion.md new file mode 100644 index 0000000..e3d1890 --- /dev/null +++ b/docs/roadmap/completion.md @@ -0,0 +1,187 @@ +# Shell completion + +Status: initial scope and all four product decisions selected; implementation +has not started. Provide canonical suggestions with alias-aware interpretation +for Bash, Zsh, and Fish through explicitly installed completion support. + +## Purpose + +Provide useful shell completion for core-only applications and applications with +optional integrations. Reuse installed command declarations and CommandKit's +routing rules so consumers need little completion-specific wiring. + +Completion helps an operator construct an invocation. It does not execute the +selected application command. Preserve application ownership of runtime behavior +and upstream ownership of configuration and prompt semantics. + +## Current baseline + +Reviewed baseline: `2301872` (`Stop flag interpretation at unknown flags`). + +- Core captures declarations and builds a routing snapshot containing canonical + commands and separate application aliases. +- [Neutral metadata](../../internal/commandmeta/metadata.go) describes command + names, descriptions, flags, boolean/value distinctions, repetition, required + flags, and operand cardinality. It has no completion choices or path hints. +- The [Cobra adapter](../../internal/cobra/parse.go) constructs a backend tree + for parsing and help. CommandKit owns execution and presentation outside that + tree; enabling Cobra's default completion command alone is insufficient. +- [Alias routing](../../route.go) resolves complete command paths and coordinates + canonical parsing with entered spellings. Completion must also handle partial + words and an empty current word. +- Invocation reporting controls ordinary output and diagnostics. Shell completion + queries need machine-readable replies independent of flags in the unfinished + command line. +- The core module uses Cobra v1.10.1 and pflag v1.0.9. Cobra supplies script + generators and completion callbacks for Bash, Zsh, Fish, and PowerShell. + See its [versioned completion documentation](https://github.com/spf13/cobra/blob/v1.10.1/site/content/completions/_index.md). + +[ADR 0013](../adr/0013-application-alias-routing.md) owns the separation between +alias routes and canonical commands. [ADR 0014](../adr/0014-invocation-reporting.md) +owns invocation reporting. This roadmap defines completion within those +boundaries; it does not establish a replacement command model. + +## Target experience + +An operator generates and loads a shell integration script, then receives +suggestions for installed commands, applicable canonical flags, and declared +value choices or paths. The selected script-generation grammar is: + +```text +app completion bash +app completion zsh +app completion fish +``` + +Consumers explicitly install a core completion declaration through the existing +installation API. The completion namespace is reserved only when installed. +Keep the machine query hidden from ordinary help, with collision validation for +its selected path. Installation must not replace an application-owned command. + +Script generation writes to the caller-selected result stream. Shell setup +instructions explain loading the script; automatic modification of shell startup +files is outside the initial implementation. + +The initial MVP suggests canonical command names and flag spellings. Completed aliases +already entered by the operator are interpreted to identify the canonical target. +For example, with `jobs` routing to `workspace jobs`, completing after +`app jobs ` can suggest the canonical children of `workspace jobs`. +Completion should preserve the text the operator has already entered. + +Matching partial canonical names, resolving completed aliases, and interpreting +an alias-only discovery prefix are distinct cases. Initially, an alias-only +prefix with no canonical target offers no command continuations. For example, +if `legacy inspect` is an alias but `legacy` has no canonical target, +`app legacy ` offers no command continuations. After the complete alias is +entered, completion uses its canonical target. Applicable flag suggestions can +still follow the existing discovery context. + +Suggested continuations must form a valid next step when inserted into the +entered route. Do not append canonical words that would create an invalid route. +Alias discovery may be omitted from the initial MVP; this is a scope choice, +not a permanent limitation of CommandKit. Suggesting alias names or alias-path +continuations remains [potential future work](deferred.md#alias-completion-and-discovery). + +### Flag suggestions + +Initially suppress already supplied singleton flags from flag-name suggestions. +Canonical and aliased occurrences count as the same flag. Keep repeatable flags +available. Keep all four reporting flags (`--quiet`, `--verbose`, `--debug`, and +`--progress`) available because later occurrences can intentionally change or +reset their settings. + +Suggestion filtering leaves accepted syntax unchanged. Operators can still type +singleton flags again under the existing repetition rules. If an operator has +already entered a repeated flag, continue completing its value according to its +hint even when its name would have been omitted from suggestions. + +## Selected initial scope + +Provide canonical command and flag suggestions, descriptions where supported by +the selected shells, alias-aware interpretation, static value choices, and +file/directory hints. Apply the same declaration facilities to application-owned +commands and optional integrations. + +Support Bash, Zsh, and Fish using the existing backend generators, with validation +in each shell. PowerShell is outside the initial supported shell set because +there is no current consumer need; this does not preclude future support. + +Static suggestions should come from captured metadata. Completion should not +invoke ordinary handlers, input/state factories, or acquisition callbacks to +obtain it. Application startup and declaration-factory effects remain owned by +the consumer, just as they do for help. + +Dynamic discovery of configured prompt names, remote resources, or other live +values is a possible later extension. Deferring it avoids selecting provider +lifetimes and latency behavior before a concrete consumer need; it is not a +permanent prohibition on dynamic completion. + +## Ownership and implementation approach + +Core owns completion context, alias interpretation, and neutral suggestions. +The internal backend adapter owns Cobra-specific types, directives, script +emission, and protocol details. Prefer the existing backend facilities where +compatible with CommandKit's grammar. Verify the adapter approach with a small +end-to-end prototype before fixing private interfaces. + +A completion request identifies completed words and the current partial word, +including an empty word after a space. Interpret only what is needed to locate +suggestions. Ordinary required-value validation and input conversion must not +reject a partially constructed invocation before completion can help fill it. +Reuse token and flag interpretation helpers where practical without changing +normal execution grammar or treating incomplete input as an executable command. + +Account for command-local flags, aliases, consumed values, `--`, attached values, +boolean assignments, short clusters, repeatable flags, and operand positions. +Keep provenance sufficient to return a replacement for the word being edited. +Completion candidates are suggestions, not an additional input validator. + +When both an operand and a flag are valid, use the operand's hint for an +empty current word after a space. Offer flag names when the operator starts +the word with `-` in a context where flags are accepted. + +Value choices and path hints belong in CommandKit-owned public metadata. Carry +them through declaration capture and neutral metadata to the adapter. Arbitrary +converter functions cannot reliably reveal their accepted values. Adding a list +of suggestions must not silently restrict the values a converter accepts. + +Provide declarative static choices with optional descriptions, file/directory +hints, and an explicit way to request no value suggestions. Unannotated values +default to no value suggestions; applicable commands and flags still complete. +Filename completion requires a path hint. This keeps unrelated filenames out of +identifier and numeric completions. The implementation plan specifies how hints +fit into existing binding declarations. + +Initially use one hint strategy per value position: static choices, files, +directories, or no value suggestions. Optional choice descriptions belong to the +static-choice strategy. Combined choices and filesystem suggestions can be +considered later if consumers need them; the initial API need not define their +merging or deduplication behavior. + +Verify the same strategy works for separated and attached flag values, such as +`app serve --config ./par` and `app serve --config=./par`. For the +attached form, preserve `--config=` and complete its value correctly. Validate +the resulting command line in each supported shell. + +Keep ordinary script generation under the existing reporting policy. A hidden +shell query is a protocol exchange: flags in the command being completed are +request data, so `--quiet` must not erase its reply and `--debug` must not append +ordinary diagnostics to it. When an unrecognized or incomplete command line +leaves no inferable completion context, return a valid empty reply that disables filename fallback. Reserve +protocol errors for failures in the query itself. Specify their wire behavior +and output ownership in the implementation plan. A completion request must not +accidentally run the target command. +Hidden protocol names are implementation details unless deliberately published. + +## Delivery plan + +The [implementation plan](implementation.md) owns the sprint sequence, API and +protocol design, and validation steps. The target includes behavioral coverage +and shell-level validation through the public consumer path in Bash, Zsh, and +Fish. + +## Deferred scope + +Alias discovery remains a potential extension beyond the MVP. Dynamic discovery +remains deferred until a concrete consumer need justifies its callback, +cancellation, error-handling, and provider-lifetime design. diff --git a/docs/roadmap/deferred.md b/docs/roadmap/deferred.md index 0f54575..32da8e2 100644 --- a/docs/roadmap/deferred.md +++ b/docs/roadmap/deferred.md @@ -25,12 +25,28 @@ unselected extensions to the delivered ConfigKit comparison. Consider them only for a concrete consumer need and a deliberate API/behavior decision under the relevant ADRs. +### Alias completion and discovery + +The [shell-completion roadmap](completion.md) selects an initial MVP with +canonical suggestions and alias-aware interpretation. Potential future work +includes suggesting command and flag alias spellings and valid continuations of +alias-only prefixes. For example, completion could suggest `inspect` after +`app legacy ` when `legacy inspect` is an installed alias. + +Alias discovery may be omitted from the MVP. This deferral does not establish a +permanent canonical-only completion contract or prohibit future alias discovery. +A later design should determine how alias suggestions are presented alongside +canonical suggestions while ensuring inserted continuations form valid next +steps. No delivery date or final API is selected here. + ## Other deferred proposals These capabilities remain outside the delivered scope and require a concrete operator or consumer need and an appropriate ownership/behavior decision: -- JSON reports, shell completion, and output-file management or reloadable export. +- JSON reports and output-file management or reloadable export. +- Shell-completion extensions beyond the initial scope in the + [completion roadmap](completion.md), including alias discovery described above. - Configuration mutation, generic value assignment, and exhaustive field-origin inventories. - Credential diagnostics beyond PromptKit's native smoke checks and additional diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index 076944d..e8578f9 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,820 +1,238 @@ -# Invocation reporting implementation plan - -Status: Stages 1–20 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: complete. - -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: complete. - -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: complete. - -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: complete. - -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: complete. - -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. - -Focused metadata and Cobra adapter tests pass. Root-package registration and -alias tests are included, but their execution is deferred until the planned API -migration restores root-package buildability. - -## Stage 6: Preserve occurrence order through the normal parser - -Status: complete. - -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. - -Focused internal package suites pass. Root reducer tests are included, but their -execution is deferred until the planned API migration restores root-package -buildability. - -## Stage 7: Connect invocation execution to one reporter - -Status: complete. - -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. - -The invocation now owns one reporter, applies ordered reporting selection before -preparation and handler execution, and finalizes normal outcomes through the -reporter. Focused internal suites pass. Root-package execution remains blocked -by the planned help/version migration and remaining legacy test callers; the -root test command was run and its compile errors are recorded for those later -steps. Focused invocation coverage has been added for reporter freshness, -selection, quiet usage guidance, early errors, and ignored output failures. - -## Stage 8: Migrate help and version presentation - -Status: complete. - -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. - -Help and version reports now render through the invocation reporter, including -quiet-mode rendering and destination-failure accounting. Tests cover quiet -success, canonical and alias help, alias-only discovery, invalid requests, and -destination failures. The internal suites pass; root-package execution remains -deferred because the existing external test package still references APIs -scheduled for the later suite reconciliation. - -## Stage 9: Add core debug events - -Status: complete. - -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. - -Routing, reporting-mode selection, and handler-completion events now use shared -Debug reporting. Early events are submitted after mode selection, and completion -is submitted after deferred messages. Focused tests cover alias identity, -selection order, quiet suppression, completion ordering, no-handler behavior, -cause privacy, and debug delivery failure. Internal suites pass; execution of -root tests remains deferred until the legacy external callers are reconciled. - -## Stage 10: Separate ConfigKit provider messages and explanations - -Status: complete. - -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. - -The ConfigKit adapter now carries independent warnings and terminal native -records separately, preserves partial values and wrapped errors, and snapshots -native writer inputs. Focused tests cover mixed records, source and comparison -side context, related locations, partial values, error identity, and messages -retained through cancellation. The ckconfig suite cannot run yet because -`diff.go`, `explain.go`, and `family.go` still use APIs scheduled for later -migration; Stage 20 will validate the assembled modules. - -## Stage 11: Migrate configuration show and validate - -Status: complete. - -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. - -Configuration show and validate now submit provider messages through the shared -reporter and render results through managed output. Tests retain acquisition -ordering, shared state, YAML framing, cancellation with partial validation -output, and cover warning visibility, terminal context, quiet rendering, and -destination failures through `Presentation`. The ckconfig tests remain -unrunnable because `sources.go`, `explain.go`, `diff.go`, and family wiring and -tests still reference APIs scheduled for later migrations; Stage 20 will run the -assembled suites. - -## Stage 12: Migrate configuration sources, explain, and diff - -Status: complete. - -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. - -Configuration sources, explanation, diff, and scope inventory now submit -provider messages through the shared reporter and render through managed output. -Native explanation rendering retains already-written partial output, while -renderer and destination failures are recorded in `Presentation` independently -of operation causes. Focused ckconfig package tests pass, including comparison -preflight, source evidence, safe reports, native forwarding, warning/context -ordering, quiet rendering, and result/diagnostic destination failures. The full -ckconfig module command still fails to compile `examples/simple`, which uses the -old invocation API and is scheduled for migration in Stage 17. - -## Stage 13: Migrate PromptKit acquisition adapters - -Status: complete. - -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. - -PromptKit engine loading now separates independent warning batches from native -terminal records and carries both through catalogs, inspection, requirements, -ConfigScope comparison, concrete request validation, and smoke acquisition. -Native rendering retains scope/side headings, source legends, and diagnostic -locations; original errors and reports returned with errors remain available. -Offline adapter tests cover mixed record separation, writer propagation, -comparison-side context, error identity, and existing request lifetimes. The -ckprompt suite cannot execute yet: compiler diagnostics identify legacy -reporting calls in `command.go`, `smoke_command.go`, and their tests, which are -scheduled for Stages 14 and 15. No compile errors were reported in the migrated -adapter files; Stage 20 will run the assembled suite. - -## Stage 14: Migrate PromptKit listing and inspection commands - -Status: complete. - -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. - -PromptKit catalog listing, definition inspection, and requirements inspection -now submit provider messages through the reporter and render complete reports -inside managed output. Acquisition failures use native terminal context when -available and preserve the original cause. Tests cover independent warning and -terminal-context delivery, successful ordinary/quiet/verbose/debug execution, -quiet encoding failure, cancellation, and result delivery observations. The -ckprompt suite cannot run yet because `validation_command.go` and -`smoke_command.go` still use the legacy reporting API scheduled for Stage 15; -Stage 20 will validate the assembled module. - -## Stage 15: Migrate request validation and smoke commands - -Status: complete. - -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. - -Concrete request validation and PromptKit smoke commands now submit passive -messages through the reporter and render confirmation, native, and aggregate -reports inside managed output. Smoke reports remain available alongside -operation failures, with native explanations and causes retained separately; -aggregate collection order and shared input/state lifetimes remain covered. -`GOTOOLCHAIN=local go test -count=1 .` passes in `integrations/ckprompt`. The -module-wide `go test ./...` reaches and passes that package but cannot compile -`examples/composed`, whose legacy API callers are scheduled for Stage 17. - -## Stage 16: Maintain a core reporting consumer - -Status: complete. - -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. - -Completion: migrated the core example command to the invocation reporter and -added a deterministic reporting command with result, warning, info, progress, -debug, recovery, failure, and partial-output scenarios. Its tests cover ordinary, -progress, verbose, debug, and quiet output, plus cause identity and terminal -explanations. `GOTOOLCHAIN=local go test -count=1 ./examples/core` and the debug -demo pass; the partial-output demo prints its completed section and terminal -explanation, then exits with status 1 as expected. - -## Stage 17: Migrate maintained integration consumers - -Status: complete. - -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. - -Completion: migrated both example-owned handlers to invocation reporters and -explicit explanations with optional causes. The ConfigKit consumer demonstrates -a provider schema warning in verbose mode, ordinary report output, and quiet -suppression. The composed consumer retains aliased help and offline smoke usage; -its tests cover a native report with an independent provider warning, terminal -context, and an operation error, plus quiet custom-command success and domain -failure. Both integration modules pass `GOTOOLCHAIN=local go test ./...`, -including both example packages. Representative verbose ConfigKit, quiet -ConfigKit, aliased quiet help, and offline PromptKit smoke commands also pass. - -## Stage 18: Reconcile the full test suite and architectural boundaries - -Status: complete. - -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. - -Completion: migrated the remaining core tests and benchmark caller to reporter, -explicit explanation/cause, and presentation-result APIs. Updated reporting -expectations for unprefixed Info, routed flag-alias parsing, quiet selection on -routing failures, and causes remaining separate from terminal explanations. -Reporter tests cover delivery states, retained failures, ignored errors, -finalization, domain statuses, quiet late handles, independent healthy -destinations, complete concurrent operations, and caller-owned writers. -`GOTOOLCHAIN=local go test -count=1 ./...` passes in the root, ckconfig, and -ckprompt modules; `GOTOOLCHAIN=local go test -race -run '^TestReporter' .` passes. -Boundary checks confirm Cobra/pflag imports stay under `internal/cobra`, public -Go documentation exposes no backend or internal types, and core does not depend -on either optional integration module. - -## Stage 19: Update canonical documentation and compatibility guidance - -Status: complete. - -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. - -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 - -Status: complete. - -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: `gofmt` left the changed Go files formatted. The root, ckconfig, and -ckprompt workspace suites pass; the root workspace-off suite and focused -reporter race suite pass. Maintained examples pass for core reporting, quiet -help/version, scoped PromptKit YAML, and aliases. The composed-example failure -test confirms an offline smoke report remains available alongside an injected -operational error and terminal context. The ignored `go.work` still includes -all three modules and was not committed. Final Markdown links and fragments and -staged and unstaged whitespace checks pass. All selected roadmap behaviors are -implemented; no release or publication action was performed. - -## 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. +# Shell completion implementation plan + +Status: ready for implementation. + +Implement the [shell completion roadmap](completion.md) from baseline +`2301872`. Follow the stages in order in one sprint. Intermediate stages may +leave unfinished wiring or a noncompiling tree; validate the assembled result +before calling the sprint complete. Use the existing ownership boundaries in +[ADR 0013](../adr/0013-application-alias-routing.md), +[ADR 0014](../adr/0014-invocation-reporting.md), and the +[architecture policy](../policy/architecture.md). Apply the +[testing policy](../policy/testing.md) to integration assertions. Keep protocol +names, candidate ordering, and backend mechanics private. + +## Stage 1: Prove the shell transport + +1. Use the Cobra version pinned in the root module. In a disposable prototype, + generate scripts with `GenBashCompletionV2(w, true)`, + `GenZshCompletion(w)`, and `GenFishCompletion(w, true)`. Give the generator + a minimal root whose name is the installed executable basename. Do not + install Cobra's completion command or execute its completion parser. +2. Supply a fixture executable that handles the generated scripts' hidden + request (`__complete` with these generator settings). Verify the actual + arguments and replies using each script in its shell. The request carries + the words through the cursor, including the partial word as its last + argument; preserve an explicitly empty last argument. Check what each + script does with the prefix of an attached value before deciding how to + encode its replacement. Cover `--config=./par`, separated path values, + spaces, an empty no-file reply, directory-only completion, and a partial + short cluster. Verify the edited line, not only the printed candidate list. +3. Use Cobra's line protocol: candidate lines with optional tab-separated + descriptions, followed by the colon-prefixed directive integer and newline. + Use the adapter's Cobra directive constants, not hardcoded numbers in core. + Map command/flag/static choices and no candidates to NoFileComp, file hints + to native file completion, and directory hints to FilterDirs. If a generated + script cannot express the selected behavior as emitted, make the smallest + adapter-owned script adjustment that preserves it and add a shell regression. + In particular, verify attached-value prefix reconstruction and Fish's + filesystem handling. Do not narrow the supported contexts to fit a script. +4. Record the observed argument and replacement conventions in the sprint + evidence. Carry forward only the adapter and fixtures needed for the final + implementation; do not commit disposable prototype machinery. + +## Stage 2: Capture completion hints + +1. Add the following public API in the root package. Add + `Completion CompletionHint` to both `FlagMeta` and `ArgumentMeta`; + existing binding constructors and their signatures stay in place. + + ```go + type CompletionChoice struct { + Value string + Description string + } + + type CompletionHint struct { /* private representation */ } + + func CompleteChoices(choices ...CompletionChoice) CompletionHint + func CompleteFiles() CompletionHint + func CompleteDirectories() CompletionHint + func NoCompletion() CompletionHint + ``` + +2. Represent the four strategies as a private discriminator and choice list. + The zero hint and `NoCompletion()` are equivalent. Copy choice slices + when constructing the hint. Capture the hint through ordinary bindings, + repeatable bindings, and `CaptureFlags`; bridge it through + `bridgeFlags` and `bridgeArguments` to neutral metadata. Use neutral + strategy and choice types in `internal/commandmeta`; backend types do not + cross the adapter boundary. +3. Keep hints independent of binding identity, requiredness, defaults, + repetition, and converters. Static choices are literal prefix matches and + do not constrain accepted values. Empty choices mean no suggestions, not + file fallback. Use ordinary boolean literals `true` and `false` for + the built-in boolean assignment case; an application boolean binding + without a hint has no value suggestions. +4. Verify caller mutation of the original choice slice cannot change captured + suggestions, repeated/captured bindings keep hints, and values absent from + a suggestion list still reach the existing converter. + +## Stage 3: Install completion as an ordinary declaration + +1. Add `func Completion(executable string) Command`. The parameter is the + executable basename the operator types, independent of the human-readable + `Identity.Name`. Use a root-only `completion` group with three runnable + children, `bash`, `zsh`, and `fish`. Use the existing declaration and + registration API (`New(..., Completion("app"))` or + `app.Register(Completion("app"))`). Keep script-specific name handling + inside completion; do not change validation of ordinary application identity. +2. Carry a private completion-installation marker with the declaration and + derive query availability from the committed routing snapshot. Use the + existing registration candidate to validate collisions in either order, + including aliases and same-batch declarations. Reserve the query's first + token only while installed: a canonical command or alias beginning with + that token would be shadowed by raw query dispatch. Reuse existing + command/alias collision rules for `completion`. Do not represent the + query as a canonical node, alias target, or public help entry. +3. Generate scripts in the internal adapter using the transport established + in Stage 1. Surface generator errors through ordinary presentation. + Use `Reporter.RenderOutput` for script generation and delivery, so + `app completion bash --quiet` follows normal reporting. Document the + basename expected by the generated scripts; handle unsupported generator + names at the completion boundary. +4. Verify opt-in behavior, root-only placement, help visibility, batch + rollback, late installation, and absence of new reserved names for an app + that does not install completion. + +## Stage 4: Resolve the entered command context + +1. Add a private core completion request that separates completed words from + the current word. Call `resolveEnteredRoute` on completed words only; + use the snapshot's canonical metadata, resolved flag-alias context, and + discovery context. Keep entered words unchanged. For canonical routes + with a runnable operand owner, use the existing canonical prefix length + to distinguish its trailing operands/options from command words. +2. Suggest canonical child names matching the partial word while the input + is still in command-path position. At a node with both children and + operands, matching children take precedence; if there are no matching + children, use the operand context when available. Check insertion against + normal routing: resolve completed entered words plus the candidate and + retain it only if it reaches the intended canonical child. Do not treat a + partial alias as already entered. After a flag or operand has ended the + command path, do not suggest children. +3. An alias-only discovery prefix provides no command continuations, but can + supply applicable canonical flags using discovery metadata and alias + mappings. Unknown routes with no valid context yield no candidates. + At root, use the installed visible commands, including built-ins and + integrations. Exclude the protocol endpoint everywhere. +4. Add context tests for root/group/runnable paths, a partial canonical + child, a complete alias and alias chain, an alias-only prefix, a canonical + child shadowed in the entered route, and flags beginning before the + complete command path. Use existing routing rules as the oracle. + +## Stage 5: Interpret flags and locate value positions + +1. Walk the completed tail using the same canonical and alias spellings and + flag token rules as normal parsing. Factor shared token classification + from `internal/cobra/flags.go` into neutral helpers where needed; keep + backend parsing and failure wording at their current owner. The completion + walk records supplied canonical flags, consumed operands, whether options + ended, and any pending value flag. It does not run Cobra dispatch, + converters, required checks, input factories, or providers. +2. A pending value takes precedence even if the current word starts with + a dash. For long equals forms, explicit boolean assignments, and short + value flags in clusters, separate the value prefix from the entered + spelling and separator. Preserve that spelling, including an alias. + For a partially typed short cluster still accepting flag members, use its + canonical short spellings for continuations; do not rewrite earlier members. + A standalone `--` ends flags unless consumed as a value. After it, + dash-looking words are operands. An unknown completed option that makes + further interpretation ambiguous yields no suggestions. +3. For flag-name suggestions, match canonical spellings and suppress already + supplied singletons by canonical identity, including occurrences through + aliases. Keep repeatable flags and the four reporting flags eligible. + When a repeated singleton is typed anyway, still complete its value. +4. For an operand, use the same cardinality allocation as `allocateOperands` + in `binding.go` without required validation: include the current word + as a placeholder, determine which binding receives that final position, + and use its hint. Extract the cardinality calculation if necessary to avoid + a second allocation policy. Excess operands receive no suggestions. + When both operand and flag positions are available, an empty word uses + the operand hint and an option-looking partial word requests flags. +5. Test pending/attached/empty values, short clusters, scoped aliases and + unavailable targets, repeats, booleans, option-looking values, interspersed + operands, terminators, and optional/repeated operands before a required + suffix. Keep existing normal execution tests green at the sprint boundary. + +## Stage 6: Assemble candidates and deliver query replies + +1. Produce a neutral result of candidate replacements, optional descriptions, + or a filesystem strategy with value context. Keep prefix preservation + distinct from matching; the adapter translates the neutral replacement + according to the shell conventions verified in Stage 1. Do not interpret + choice values as shell source. Normalize description line breaks and omit + candidates the line protocol cannot represent rather than changing what + an inserted value means. Do not add execution-time validation for these + presentation limitations. +2. In `Execute`, after normal receiver/context checks and before ordinary + routing, recognize the exact raw query token only on an installed snapshot. + Treat all following tokens as data. Split off the final word; a missing + current-word argument is a malformed transport request, distinct from an + empty string. Use the current snapshot on each query, including after + later registration. Do not enter normal parsing, reporting selection, + input preparation, or handler execution for this path. +3. Write the adapter response only to normalized `Streams.Out`, with + managed output delivery in ordinary mode. A valid query with no inferable + context returns success and a NoFileComp reply. For a malformed request + or query construction failure, return an operational outcome and, if the + output is still usable, emit an error directive with no candidates. + Explanations go to diagnostics, never into the reply. Preserve write + failure evidence through normal presentation bookkeeping; do not retry + a broken output stream. No generated script should consume ordinary + usage guidance or debug output as a candidate. +4. Test query dispatch via `App.Execute`, including explicit empty last word, + no-context reply, malformed request, writer failure, hidden discovery, + later registration, and target words containing `--quiet` and `--debug`. + Use counter fixtures to prove target handlers, converters, factories, + and providers are untouched. Verify no special dispatch without installation. + +## Stage 7: Annotate maintained commands and examples + +1. Annotate static format/scope flags where their choices already come from + fixed command metadata or literals. Use the same values as the existing + version, config, and PromptKit command implementations; omit scope hints + that would advertise values not supported by that installed declaration. + Mark existing config/overlay filename flags as files where the binding + takes a filename. Leave prompt IDs, dynamic selectors, and composite + assignments unannotated. Do not infer domain semantics or load providers. +2. Add explicit installation to the maintained core and composed examples. + Demonstrate a static choice, a path hint, and an already-entered alias + with no new runtime dependency. Include an integration-level check + that installed hints reach completion without acquisition. +3. Update GoDoc, the CLI reference, and consumer/example instructions with + actual syntax, basename selection, manual script loading for each shell, + and examples of hints. Keep the wire protocol private. Once delivered, + update the feature status and keep alias discovery and dynamic discovery + in deferred work. + +## Stage 8: Validate the assembled sprint + +1. Exercise the generated scripts in Bash, Zsh, and Fish using a built fixture + executable, a disposable directory with filenames and directories containing + spaces, and isolated shell configuration. Verify actual completion output + and replacement behavior. Cover canonical commands, an entered alias, + static choices and descriptions, no fallback, file/directory hints in + separated and attached values, and the empty operand/leading-dash rule. + Use a PTY or a shell's native completion test interface where appropriate. + Syntax checking alone is insufficient. Record shell versions and the + commands or harness used so the evidence is reproducible. +2. Run the root and both optional module suites under the local workspace + procedure in [development.md](../development.md), plus the root suite + with `GOWORK=off`. Keep shell-dependent checks outside the default Go + suite unless the existing environment provides those shells; an absent + shell is missing acceptance evidence, not a passing check. +3. Verify no backend types in public declarations, no reverse optional-module + dependency, and no changes to ordinary routing, flag acceptance, or report + behavior outside the selected completion scope. Review documentation links, + formatting, and the final diff. Record the actual validation results. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md index 71e2a8d..11f192d 100644 --- a/docs/roadmap/remediation.md +++ b/docs/roadmap/remediation.md @@ -5,7 +5,7 @@ Status: remediation complete; all 7 findings addressed. ## Review scope Reviewed the reporting implementation from `2a1096b` through `7c035cc` against -the [feature roadmap](reporting.md), [implementation plan](implementation.md), +the [feature roadmap](reporting.md), [implementation plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md), [ADR 0014](../adr/0014-invocation-reporting.md), [ADR 0005](../adr/0005-invocation-outcomes.md), and the [architecture policy](../policy/architecture.md). @@ -214,7 +214,7 @@ that failed before writing and a rejected result write. The corresponding reporter and execution tests currently assert this generic text, so they preserve the gap rather than the selected distinction. -[Stage 4](implementation.md#stage-4-implement-deferred-delivery-and-finalization) +[Stage 4](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md#stage-4-implement-deferred-delivery-and-finalization) requires a useful core-owned explanation when presentation turns success into failure. The roadmap assigns handling of reporting failures to CommandKit and distinguishes healthy diagnostic destinations from failed result destinations. diff --git a/docs/roadmap/reporting.md b/docs/roadmap/reporting.md index 994f2d3..c1ce509 100644 --- a/docs/roadmap/reporting.md +++ b/docs/roadmap/reporting.md @@ -13,7 +13,7 @@ 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 and final validation are complete; Stages 1–20 are complete. The [implementation -plan](implementation.md) records the stage order and validation evidence. +plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) records the stage order and validation evidence. ## Purpose @@ -872,7 +872,7 @@ 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 +The [implementation plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) defines the concrete migration steps, focused validation, and completion criteria. This roadmap defines the target behavior and selected policy choices. @@ -887,4 +887,4 @@ target behavior and selected policy choices. 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. +[implementation plan](https://forge.maximumdirect.net/base-layer/commandkit/src/commit/230187296fae5253cb1773f16c2f1d1a39499ed0/docs/roadmap/implementation.md) owns their delivery sequence.