# Computational efficiency roadmap Status: proposed improvements; OD-1 and OD-2 resolved; implementation has not begun. Date: 2026-10-09. ## Purpose and authority Reduce repeated work and avoidable allocations in CommandKit's command dispatch, registration, and inspection reports. Favor straightforward changes with clear benefits, and use measurements to decide whether more complex optimizations are worth maintaining. This document owns the proposed improvements, priorities, and completion evidence. The [architecture policy](../policy/architecture.md), accepted [ADRs](../adr/), [Go declarations](../../app.go), and [CLI reference](../cli.md) continue to govern behavior. Follow the [agent policy](../policy/agents.md) for proportionate implementation and the [testing policy](../policy/testing.md) for validation. These proposals do not establish new public performance or concurrency guarantees. ## Reviewed baseline The efficiency review examined commit `54cfbd8` with a clean worktree. Its findings come from source inspection; no benchmarks or allocation profiles were run. Complexity observations identify scaling costs, not measured bottlenecks or promised speedups. Recheck the affected implementation before starting work. | ID | Observed work | Proposed result | Priority | | --- | --- | --- | --- | | PF-01 | PromptKit text reports are built even for YAML requests. | Render only the requested format and avoid redundant report buffers. | First pass | | PF-02 | Selected-command lookup scans a map; each ancestor is rediscovered from the root. | Direct declaration lookup and ancestry traversal proportional to path depth. | First pass | | PF-03 | Every invocation translates and sorts metadata; help and usage construct another backend tree. | Reuse immutable metadata and the invocation's prepared tree. | Measure and improve after the first pass | | PF-04 | Aggregate YAML framing splits every line and copies the complete native document. | Inspect only the opening lines and retain a complete framed buffer for delivery. | First pass | | PF-05 | Each registration copies the existing top-level registry. | Prepare new entries separately and install a validated batch atomically. | Lower priority | | PF-06 | Scope ordering, lookup, and selection repeat; selector duplicate checks scan previous entries. | Prepare stable scope metadata once and use direct duplicate checks. | Lower priority | The implemented package inventory remains owned by the [internal overview](../internal/overview.md). The target is internal improvement within the existing root facade and Cobra adapter; no additional public package or consumer registration API is proposed. ## Target behavior and ownership Optimizations preserve the existing contracts rather than changing operator or consumer workflows: - Keep Cobra/pflag objects and operations inside the internal adapter, following [ADR 0003](../adr/0003-public-facade.md). - Keep parsed values, collections, and presence independent between invocations. [ADR 0002](../adr/0002-cobra-backend.md) permits safe reuse; rebuilding backend storage is an implementation choice. Caller-owned state retains its lifecycle. - Preserve registration validation, reserved command ownership, and complete batch validation before changing the registry, as documented in [command declarations](../../command.go) and [registration](../../registry.go). - Keep metadata construction, help, and version independent of provider acquisition under the architecture policy. - Preserve owning-library rendering and confidentiality semantics, aggregate document order, and acquisition of all selected views before `config show` output under [ADR 0007](../adr/0007-native-yaml-reports.md). - Preserve cancellation, diagnostic delivery, outcome classification, and reporting of partial output and write failures under [ADR 0005](../adr/0005-invocation-outcomes.md). Registration and command metadata belong to the root implementation. Backend indexes and invocation machinery belong to `internal/cobra`. Report formatting and scope preparation remain with the corresponding root handlers. Acquisition, configuration resolution, and provider lifetime remain with the existing integration contracts and consuming applications. ## Proposed improvements ### PF-01: Render only the requested PromptKit format In [PromptKit handlers](../../promptkit.go), `runPromptKitPrompt` calls `formatPromptText` before `writePromptKitReport` chooses a format. `runPromptKitProfile` similarly calls `formatProfileText` unconditionally. The profile text formatter serializes `ExtraParams` as nested YAML; a YAML request then serializes those parameters again as part of the structured report. Text delivery also copies an already completed report into another builder. Choose the requested formatter before rendering. Use a straightforward buffer or completed report representation that avoids the redundant text-buffer copy. Continue using the existing structured report representation and YAML encoder; the optimization concerns when rendering occurs and how its result is delivered. Completion evidence should show unchanged text and YAML report semantics, including `ExtraParams`, diagnostics, and delivery failures, with eliminated unused text construction for YAML requests. Measure prompt input collections and profile parameter maps large enough to expose the redundant work. ### PF-02: Index command declarations and ancestry In the [Cobra adapter](../../internal/cobra/parse.go), `declarationFor` scans the declaration-to-backend map to find a selected backend command. `pathFor` calls `parentOf` from the root for every ancestor. For N command nodes and selected depth D, repeated parent searches can take O(N × D) work; a chain can produce quadratic work. Record a backend-to-declaration mapping during construction. Build parent links alongside it, or traverse Cobra's existing parent relationships internally. Prefer an implementation that reconstructs only the selected path rather than storing a separate complete path for every node. Declaration lookup should be constant time, with path construction proportional to D after tree preparation. Exercise shallow, wide, and deeply nested declarations through dispatch, help, and usage. Preserve exact registered-path matching and error classification. This improvement removes redundant searches; constructing the complete backend tree still has a separate cost addressed by PF-03. ### PF-03: Reduce command-tree reconstruction [Metadata translation](../../parser.go) copies and sorts the registered tree on every invocation, including flag and operand declarations. The adapter then builds backend commands and flag sets for all nodes. Help and usage rendering build another complete backend tree after parsing has already built one. Pursue two improvements: 1. Retain the invocation's prepared backend tree inside the adapter and use it for parsing, help, and usage. The root coordinates these operations without receiving Cobra/pflag objects. Keep the internal coordination API narrow. 2. Prepare or lazily cache immutable bridge metadata and sorted child order per `App`. Refresh that derived state after successful registration. Failed registration must leave the previously registered commands usable, including their help and dispatch behavior. Metadata caching principally benefits repeated `Execute` calls. Avoiding a second backend construction also benefits a single CLI help or usage request. Measure both cases separately, including the cost of app construction and registration for consumers that execute only once. Under the selected OD-1 approach, construct fresh mutable backend parse state for each invocation, reuse that state within the invocation, and cache immutable metadata between invocations. Reusing mutable backend trees across invocations is deferred beyond this target. Measurements may motivate reconsidering it in future work. No public freeze step, backend selector, or concurrent-dispatch guarantee is needed for these improvements. ### PF-04: Reduce aggregate YAML preamble scanning In [configuration display](../../show.go), `hasYAMLDirective` and `frameEffectiveYAML` split the complete document into lines before examining its opening content. These splits scan all bytes and allocate a slice entry for each line, even when the framing decision can be made immediately. Framing then allocates a complete copy alongside the native buffer. First, scan the preamble with byte offsets, stopping when the directive or marker decision is complete. Share the resulting framing analysis where useful so directive detection and scope-label placement do not independently scan the same preamble. Avoid a document-wide line index and unnecessary string conversions. Under the selected OD-2 approach, retain the native render buffer and assemble a complete framed buffer for each document before delivery. This keeps delivery and write-failure handling straightforward. The full document copy remains an accepted cost of this target; the optimization removes the document-wide line index and redundant preamble scanning. Preserve native bytes, directive placement, inline document content and block scalars, scope-label escaping, and boundary newlines according to the CLI contract. Keep single-scope native delivery direct. Aggregate acquisition remains complete before output; the current code buffers one rendered document at a time, not every scope's rendered bytes simultaneously. Measure documents with many short lines as well as large values. The initial target removes avoidable scans and allocations; complete rendering and delivery will still require work proportional to output size. ### PF-05: Avoid repeated registry copying [Registration](../../registry.go) copies all existing top-level entries for each `Register` call. Registering R top-level commands individually therefore produces O(R²) cumulative map-copy work, apart from validation and declaration cloning. This is a construction cost, not work performed by a registered handler. Validate declarations, check collisions against both existing and pending entries, and prepare owned new entries in temporary storage. Install them only after the complete batch succeeds. Preserve declaration ownership and atomic validation without copying every existing map entry. Compare individual and batch registration at representative sizes. Batch registration is already available to consumers; adopting it is an optional consumer optimization, not a new requirement. Coordinate this work with PF-03's metadata refresh so registration has one clear completion point. ### PF-06: Prepare stable configuration scope metadata [Scope selection](../../selectors.go) sorts scope declarations and repeatedly searches the scope slice. Aggregate selection and handler acquisition each look up every scope by name, producing quadratic scope-search work. Selection also occurs during preflight and again in the handler. In [suite normalization](../../config.go), selector duplicate checking compares each selector with all previous selectors; PromptKit already uses name and short-name maps for the equivalent check. Prepare stable scope order and a name lookup during suite registration, keeping that derived data private. Use direct name and short-name checks for selector duplicates. Assess retaining the selected scopes in invocation-owned input after preflight if repeated selection remains significant; keep selector applicability and per-invocation contexts fresh. Measure the normal small scope set before adopting additional indexes for selector applicability. Preserve scope order, declared operation availability, and scope-aware selector validation under [ADR 0009](../adr/0009-configuration-scopes.md). Do not invoke acquisition while preparing this metadata. ## Recommended sequence and measurement 1. Establish focused before-change measurements for PF-01, PF-02, and PF-04, then implement conditional formatting, direct command lookup/ancestry, and YAML prefix scanning as independently reviewable changes. 2. Measure complete dispatch paths, then implement PF-03's reuse within an invocation and immutable metadata caching. Compare the resulting runtime gains with the coordination cost and retained memory. 3. Evaluate PF-05 and PF-06 using the first-pass evidence and expected consumer sizes. Record a deferral if a proposed change adds complexity without a worthwhile benefit. 4. Record remaining costs after the selected improvements. Mutable backend reuse across invocations and segmented YAML delivery remain future possibilities beyond this target; any reconsideration should use the measurements and a deliberate change to the selected approach. Use Go benchmarks with controlled, offline fixtures when implementation work is authorized. Keep external loading and service latency out of isolated CommandKit measurements, and identify when an integration measurement includes provider work. Include: | Area | Representative comparisons | | --- | --- | | Dispatch | Small and larger registries; wide and deep trees; few and many flags; successful commands, help, and usage errors. | | Lifecycle | Construction, registration, and first execution versus repeated execution on an existing `App`. | | Reports | Prompt text/YAML; profile text/YAML with varied parameter maps; aggregate configuration documents with varied size and line count. | | Registration and scopes | Individual/batch registration; small and larger scope and selector sets. | Record elapsed cost, bytes allocated, and allocations per operation with the Go version, machine, fixture dimensions, and benchmark scope. Use repeated samples for comparisons; profile CPU or allocation behavior when it helps explain a remaining cost. Account for memory retained by caches as well as allocation reductions. Avoid combining every fixture dimension into a large benchmark matrix without a specific question. Choose behavioral validation according to each change's risks and existing coverage. Important cases include fresh presence and collections across runs, registration after earlier execution, failed registration, help without provider loading, YAML framing, cancellation, and partial output. Behavioral tests should protect the existing contracts; benchmark results assess efficiency without locking in private data structures or exact helper-call sequences. These measurements guide implementation choices. They do not establish fixed timing thresholds, allocation budgets, or additional release gates. ## Completion and documentation For each PF item, record whether it was implemented, deferred, or narrowed, alongside its change reference, relevant behavioral validation, and measurement results. An unmeasured improvement must be described as such. Completion means the selected changes preserve the existing contracts and have evidence supporting their claimed benefit; it does not require implementing every speculative reuse option. Update [internal documentation](../internal/overview.md) when implemented mechanics change. Update public GoDoc or the CLI reference only when their owning contracts need clarification. Keep proposal status and performance evidence in this roadmap or a subsequent implementation plan. Provider caching, consumer loader redesign, removing copies required for value ownership, and replacing Cobra are outside this target. They require their own concrete motivation and review rather than following automatically from a performance optimization. ## Resolved Decisions The following approaches were selected on 2026-10-09. Both are implementation choices within the existing public contracts. No significant open decisions remain for this roadmap's scope. ### OD-1: How far should backend reuse extend? **Selected approach:** Adopt the recommended approach: reuse the prepared backend within one invocation and cache immutable metadata between invocations, while constructing fresh mutable backend state for each `Execute`. **Reasoning:** This removes repeated help/usage work and metadata translation while keeping invocation isolation straightforward. Measure the remaining backend construction cost to inform future work. The selection defines the PF-03 target without establishing a permanent architectural restriction. **Alternative considered:** Retain a mutable backend tree per `App` and reset it before each invocation. This can remove more command and flag-set construction work for consumers that execute repeatedly. It also retains more memory and requires careful reset of parsed values, presence, operands, contexts, streams, and other backend state, plus refresh after registration. The added lifecycle complexity is deferred until measurements justify reconsideration and behavioral evidence establishes independent invocations. A CLI that executes only once receives little benefit from this additional reuse. ### OD-2: How much buffering should aggregate YAML retain? **Selected approach:** Adopt the previously listed alternative: retain the complete framed buffer after replacing the line splits with prefix scanning. **Reasoning:** This keeps delivery simple and avoids additional writes for each document. It accepts the second document allocation and copy while removing the line index and unnecessary scanning. Measure the resulting allocation cost, particularly for large reports, without making segmented delivery part of this implementation target. **Alternative considered:** Retain only the native render buffer and deliver framing and native slices as separate segments. This can reduce peak allocation and copying while keeping native rendering complete before delivery. It requires accounting for cancellation and partial output across segment writes and may increase writer-call overhead. It remains a viable future optimization if the selected approach's measured memory cost warrants the additional delivery logic.