diff --git a/README.md b/README.md index 49fada0..2dfe5b6 100644 --- a/README.md +++ b/README.md @@ -22,20 +22,13 @@ The [consumer guide](docs/consumers/guide.md) links to two maintained examples: - [Consumer guide](docs/consumers/guide.md) - [Internal package overview](docs/internal/overview.md) - [Maintainer release procedure](docs/release.md) -- [Computational efficiency roadmap](docs/roadmap/performance.md) -- [Performance implementation record](docs/roadmap/implementation.md) - [Architecture policy](docs/policy/architecture.md) - [Policy provenance](docs/policy/meta.md) -## Planning history and future work +## Future work and history -- [Initial delivery and deferred capabilities](docs/roadmap/initial.md) -- [Completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -- [Completed ReleaseKit implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/c0c03285f7beac3e96f1708b655c1eb2add35e79/docs/roadmap/implementation.md) -- [Historical CLI planning](docs/roadmap/01-cli-plan.md) -- [Completed dispatcher planning](docs/roadmap/02-dispatch.md) -- [Completed backend planning](docs/roadmap/03-backend.md) -- [Completed facade planning](docs/roadmap/04-facade.md) +- [Deferred capabilities and proposals](docs/roadmap/deferred.md) +- [Completed planning and implementation records in Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap) CommandKit is licensed under the [LGPL v3.0 or later](COPYRIGHT). diff --git a/docs/development.md b/docs/development.md index b047a35..552fac3 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,7 +1,7 @@ # Developing CommandKit CommandKit currently contains adopted repository policies, accepted architectural -decisions, implementation plans, identity and outcome primitives, typed command +decisions, identity and outcome primitives, typed command declarations, an instance-owned registry, a Cobra-backed routing and parsing adapter, public `App.Execute` coordination, and generated help/version commands. Configuration suite registration, scope discovery, ConfigKit validation and @@ -52,23 +52,20 @@ canonical documentation owners. | Dispatcher, registration, or typed inputs | [Command declarations](../command.go), [bindings](../binding.go), [invocation](../execute.go), and [ADR 0001](adr/0001-command-dispatch-and-inputs.md) | | Backend integration | [Internal overview](internal/overview.md), [adapter implementation](../internal/cobra/parse.go), and [ADR 0002](adr/0002-cobra-backend.md) | | Public facade or adapter boundaries | [Internal overview](internal/overview.md), [ADR 0003](adr/0003-public-facade.md), and the architecture policy | -| Deferred capabilities and delivery scope | [Initial feature target](roadmap/initial.md#deferred-capability-targets) and [explicit deferrals](roadmap/initial.md#explicit-deferrals) | -| Initial planning history | [CLI](roadmap/01-cli-plan.md), [dispatcher](roadmap/02-dispatch.md), [backend](roadmap/03-backend.md), [facade](roadmap/04-facade.md), and [completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) | -| Release tooling | [Maintainer release procedure](release.md) and [ReleaseKit upgrade roadmap](roadmap/releasekit.md) | -| Performance work | [Computational efficiency roadmap](roadmap/performance.md) and [performance implementation record](roadmap/implementation.md) | +| Deferred capabilities and proposals | [Deferred work](roadmap/deferred.md) | +| Completed planning and implementation history | [Retired records in Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap) | +| Release tooling | [Maintainer release procedure](release.md) | +| Performance maintenance | [Internal overview](internal/overview.md), existing benchmarks, and [deferred efficiency work](roadmap/deferred.md#possible-further-efficiency-work) | | Licensing or incorporated material | [Project grant](../COPYRIGHT), [license texts](../LICENSE), and [attribution](oss/attribution.md) | | Policy provenance | [Policy provenance](policy/meta.md) | Read all applicable rows for cross-cutting work. Go declarations and GoDoc own current exported contracts; the CLI reference owns operator behavior. The -initial numbered roadmaps are completed planning records. The [maintainer release procedure](release.md) owns current release operations. -The completed ReleaseKit adoption records remain available in Git history. The -[performance roadmap](roadmap/performance.md) and its implementation record -own the efficiency target and evidence. Retained illustrations and historical -staged instructions are not current API references or assignments to restart -implementation. Future capabilities remain explicitly identified in their -feature roadmaps. +Completed roadmaps and implementation evidence remain available in Git history; +they are not assignments to restart completed work. The +[deferred-work record](roadmap/deferred.md) preserves future capability targets +and unselected proposals separately from current contracts. ## Documentation validation @@ -87,8 +84,8 @@ git diff --cached --check -- '*.md' COPYRIGHT These commands do not cover untracked files. Review their contents and whitespace before staging, or use the staged check after staging only the intended files. -Sibling-checkout evidence links in the CLI planning record are historical review -references, not build dependencies. Implemented contracts belong in CommandKit +Sibling-checkout references in retired planning records are historical review +evidence, not build dependencies. Implemented contracts belong in CommandKit under their canonical owners. Run `go test ./...` from the repository root to compile the module and run its diff --git a/docs/policy/agents.md b/docs/policy/agents.md index 0cebfa9..0c8c776 100644 --- a/docs/policy/agents.md +++ b/docs/policy/agents.md @@ -2,7 +2,7 @@ **Base Policy Version:** 1.3 -**Last Updated**: 2026-10-06 +**Last Updated**: 2026-10-08 **Upstream Source:** [agents.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/agents.md) @@ -56,8 +56,9 @@ invariant, not from the convenience of the selected implementation. Explain the specific failure it prevents and why a less restrictive implementation cannot satisfy the contract. -The CLI roadmap distinguishes accepted choices from remaining proposals. Do not -approve proposed commands, grammar, statuses, or illustrative API declarations +The [deferred-work record](../roadmap/deferred.md) distinguishes future proposals +from accepted contracts. Do not approve proposed commands, grammar, statuses, or +illustrative API declarations merely by repeating them in implementation or tests. Cobra/pflag defaults do not independently establish CommandKit contracts. diff --git a/docs/policy/architecture.md b/docs/policy/architecture.md index 3ef3826..cf2dd1e 100644 --- a/docs/policy/architecture.md +++ b/docs/policy/architecture.md @@ -2,7 +2,7 @@ **Base Policy Version:** 1.3 -**Last Updated**: 2026-10-07 +**Last Updated**: 2026-10-08 **Upstream Source:** [architecture.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/architecture.md) @@ -181,10 +181,10 @@ logging system, hosted service, or standalone application. Shared vocabulary is recommended for application-owned commands; their names and domain behavior remain application choices. -The [CLI roadmap](../roadmap/01-cli-plan.md) distinguishes accepted operator -choices from remaining command and grammar proposals. Backend defaults and -incidental consumer behavior do not establish new contracts. A replacement -backend must preserve published CLI behavior or follow deliberate compatibility +Accepted ADRs and current CLI/API owners define selected contracts; the +[deferred-work record](../roadmap/deferred.md) preserves remaining proposals. +Backend defaults and incidental consumer behavior do not establish new contracts. +A replacement backend must preserve published CLI behavior or follow deliberate compatibility changes under the release policy. Base restrictions and guarantees on selected requirements. Configuration and diff --git a/docs/roadmap/01-cli-plan.md b/docs/roadmap/01-cli-plan.md deleted file mode 100644 index 5df155b..0000000 --- a/docs/roadmap/01-cli-plan.md +++ /dev/null @@ -1,133 +0,0 @@ -# CommandKit CLI planning record - -Status: initial CLI planning complete; remaining proposals deferred. - -Original review: 2026-10-06. Reconciled: 2026-10-07. - -## Purpose and current owners - -This document preserves the initial command-suite review and identifies remaining -future work. Its completed implementation tasks and obsolete contract drafts -have been retired. The [initial feature target](initial.md) and -[completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -record delivery scope and execution history. - -The [CLI reference](../cli.md) owns implemented commands, syntax, formats, and -outcomes. Go declarations and GoDoc own exact exported APIs; the -[consumer guide](../consumers/guide.md) explains integration. Accepted ADRs own -architectural rationale, and the [architecture policy](../policy/architecture.md) -owns responsibility boundaries. This planning record does not define a second -current command contract. - -## Completed initial scope - -| Planning area | Delivered boundary and current reference | -| --- | --- | -| Discovery and identity | Generated [help](../cli.md#help) and [version reporting](../cli.md#version). | -| Configuration inspection | [Scope discovery](../cli.md#configuration-scopes), validation, native display including aggregate display, sources, and path explanation. | -| PromptKit integration | Engine configuration scope and optional [named prompt/profile inspection](../cli.md#promptkit-definition-inspection), registered independently. | -| Common command infrastructure | Instance registry, typed inputs, presence, routing, and outcomes; see the [consumer guide](../consumers/guide.md) and [internal overview](../internal/overview.md). | - -CommandKit owns its standard families. Applications retain custom commands, -source selection, schema/domain work, acquisition callbacks, and executable -lifecycle. Migration of existing applications remains separate work; the -maintained [simple](../../examples/simple/README.md) and -[composed](../../examples/composed/README.md) consumers demonstrate library usage. - -## Superseded proposal choices - -The following entries are historical reconciliation notes. They summarize why -older drafts no longer describe the selected implementation; use the linked -owner for the complete current contract. - -| Earlier proposal, now superseded | Selected result and owner | -| --- | --- | -| Bare validation defaults to every scope | Configuration operations default to `app`; aggregate validation/display is explicit. See [configuration scopes](../cli.md#configuration-scopes). | -| Reject repeated singleton flags | Last occurrence supplies the value; every supplied occurrence is converted. See [registered syntax](../cli.md#registered-command-syntax). | -| Prompt inspection uses `--prompt-version` | It uses `--version`. See [definition inspection](../cli.md#promptkit-definition-inspection). | -| Rich profile reports await an upstream provider-parameter redaction API | Current public inspection supplies effective `ExtraParams`, included without additional redaction requirements. See [profile reports](../cli.md#promptkit-definition-inspection). | -| Fix application root/overlay interpretation in CommandKit, reject empty config values, and derive PromptKit selection from one prescribed root | Values and presence are passed to application callbacks, which interpret them. See [scope integration](../consumers/guide.md#a-configuration-scope) and [selection declarations](../../config.go). | -| Validation failure always emits no success report | Completed scope records can precede a later failure. See [validation](../cli.md#validate-configuration). | -| Native display has no format flag | `config show --format yaml` is accepted. See [effective display](../cli.md#show-effective-configuration) for syntax and framing. | -| Scope inventory includes description/default fields; sources use a prescribed table | The selected report shapes are defined in [scope discovery](../cli.md#configuration-scopes) and [source inventory](../cli.md#list-configuration-sources). | -| Root `app --version` is a standard entry point | The delivered entry point is `app version`; text can include revision and YAML has explicit identity fields. See [version reporting](../cli.md#version). | -| Blank definition IDs are usage failures | Missing operands are usage failures; explicitly blank values reach owning inspection and produce operational results. See [definition inspection](../cli.md#promptkit-definition-inspection). | -| CommandKit automatically coordinates shared loads and dependencies | Applications compose acquisition and may use invocation-local caches. See [consumer integration](../consumers/guide.md) and the composed example. | - -The selected namespace/resource-first grammar, capability-based family assembly, -application-focused default version, native aggregate YAML, and initial JSON -deferral remain reflected in the accepted ADRs and delivered target. The earlier -alternatives are review history, not unresolved implementation choices. - -## Deferred work and remaining proposals - -### `config diff` - -Semantic comparison is deferred pending supported upstream safe snapshot APIs. -[ADR 0008](../adr/0008-semantic-configuration-diff.md) owns its accepted comparison -and sensitivity-gap decisions. The [deferred capability target](initial.md#deferred-capability-targets) -records dependencies. - -Exact comparison selection syntax and report layout remain future design work. -The original proposal considered separate right-side root/overlay selection, -shared versus independent domain context, and an optional assertion mode. None -of those flags or modes is installed or promised by the initial implementation. -CommandKit should use owning public APIs rather than compare rendered YAML or -implement another configuration engine. - -### PromptKit catalogs - -Prompt/profile listing is deferred pending public catalog APIs. Catalog resource -names and enumeration/report details can be specified when supported APIs exist; -CommandKit does not enumerate by reparsing PromptKit configuration YAML. See the -[deferred capability target](initial.md#deferred-capability-targets). - -### Other proposals outside the initial delivery - -Configuration mutation, reloadable export, credential diagnostics, live provider -probes, shell completion, exhaustive field-origin inventories, generic value -assignment, additional component identity registration, and domain artifact -catalogs remain outside the initial scope. Their inclusion requires a concrete -operator purpose and an appropriate ownership/behavior decision. JSON remains -deferred without a commitment to add it. - -Execution, rendering, serving, and session operations remain application-owned. -Shared vocabulary is guidance under [ADR 0006](../adr/0006-command-grammar.md), -not a reserved implementation contract for every consumer. - -Application migrations should replace divergent standard paths and update -subprocess consumers and documentation for intentional breaking changes. The -original review considered Scriptorium/Notarius followed by Audita/Narratio; -that ordering is historical evidence, not a completed migration or mandatory -adoption sequence. Future capabilities can be adopted independently. - -## Historical review evidence - -The initial review on 2026-10-06 compared Audita's `print-effective`, Notarius's -`effective`, and Narratio/Scriptorium's `show`; inconsistent scope/source reports; -repeated dispatch/loading/report plumbing; and differing help, syntax, and status -conventions. Those differences informed the shared standard, rather than imposing -compatibility requirements. Narratio's subprocess interpretation of application -statuses also demonstrated the need to coordinate consumer adoption. - -Evidence sources, relative to this roadmap in the sibling workspace checkouts: - -- [Audita CLI contract](../../../audita/docs/cli.md) and - [configuration parsing](../../../audita/internal/cli/config_input.go). -- [Narratio CLI contract](../../../narratio/docs/cli.md), - [configuration inspection](../../../narratio/internal/app/config_commands.go), - and [comparison](../../../narratio/internal/app/config_diff.go). -- [Notarius CLI contract](../../../notarius/docs/cli.md) and - [configuration commands](../../../notarius/internal/cli/configkit_commands.go). -- [Scriptorium CLI contract](../../../scriptorium/docs/cli.md), - [application inspection](../../../scriptorium/internal/adapter/cli/config.go), - and [framework inspection](../../../scriptorium/internal/adapter/cli/framework_config.go). -- [ConfigKit inspection API](../../../ConfigKit/inspection.go), - [source records](../../../ConfigKit/records.go), and - [configuration contract](../../../ConfigKit/docs/config.md). -- [PromptKit configuration inspection](../../../promptkit/configuration_inspection.go) - and [consumer guide](../../../promptkit/docs/consumers/pkg-promptkit.md). - -These links identify sibling-checkout evidence from that review. They are not -build dependencies, permanent implementation references, or claims about the -applications' present adoption status. Current contracts are owned in CommandKit. diff --git a/docs/roadmap/02-dispatch.md b/docs/roadmap/02-dispatch.md deleted file mode 100644 index 04faa89..0000000 --- a/docs/roadmap/02-dispatch.md +++ /dev/null @@ -1,57 +0,0 @@ -# CommandKit dispatcher planning record - -Status: initial dispatcher implementation complete. - -Original planning: 2026-10-06. Reconciled: 2026-10-07. - -## Authority and current owners - -[ADR 0001](../adr/0001-command-dispatch-and-inputs.md) owns the dispatcher, -registry, and typed-input decisions and rationale. The -[architecture policy](../policy/architecture.md) owns responsibility boundaries. -This document records completion of the initial dispatcher design; the -[completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -preserves its execution history. - -The registry, typed inputs, command/group APIs, invocation coordination, and -outcomes are implemented. Their exact contracts are owned by Go declarations -and GoDoc, rather than the early illustrations formerly maintained here. - -| API area | Current owner | -| --- | --- | -| Application construction and registration | [App/New](../../app.go) and [App.Register](../../registry.go) | -| Typed command declarations, groups, and presence | [CommandSpec, NewCommand, Group, WithChildren, Supplied](../../command.go) | -| Typed flag and operand bindings | [Binding helpers](../../binding.go) | -| Invocation and result delivery | [App.Execute](../../execute.go), [Invocation/Streams](../../identity.go), and [Outcome](../../outcome.go) | -| Standard integration registration | [Configuration suite](../../config.go) and [PromptKit suite](../../promptkit.go) | - -The [consumer guide](../consumers/guide.md) explains assembly and callback usage. -The [CLI reference](../cli.md) owns syntax and operator behavior; the -[internal overview](../internal/overview.md) owns implemented package mechanics. - -## Completed design and evidence - -The initial work delivered instance registration, composable nested groups, -typed handlers and bindings, presence-aware input, capability-based installation, -lazy acquisition, and distinct shared/domain outcomes. The original `Supplied` -illustration is now a public declaration; application-specific restore inputs -remain consumer examples rather than proposed CommandKit types. - -The [simple](../../examples/simple/README.md) and -[composed](../../examples/composed/README.md) consumers demonstrate the API with -configuration inspection and a custom session command. The completed plan -records behavioral evidence for routing, ownership conflicts, help, invocation -state, cancellation, output failures, and domain outcome preservation. - -Completed constructor/binding/outcome design tasks and implementation assignments -have been retired from this roadmap. Concurrent dispatch remains outside the -initial target under the [feature roadmap](initial.md#explicit-deferrals). - -## Remaining adoption work - -Applications can migrate their routers and repeated standard handlers to the -implemented API, update documentation and subprocess consumers for breaking -changes, and retain their domain command behavior. Migration is separate from -library completion; this record does not claim that the sibling applications -have adopted CommandKit. Deferred standard capabilities are tracked in the -[feature roadmap](initial.md#deferred-capability-targets). diff --git a/docs/roadmap/03-backend.md b/docs/roadmap/03-backend.md deleted file mode 100644 index 116da56..0000000 --- a/docs/roadmap/03-backend.md +++ /dev/null @@ -1,54 +0,0 @@ -# CommandKit backend planning record - -Status: initial Cobra/pflag backend implemented. - -Original planning: 2026-10-06. Reconciled: 2026-10-07. - -## Authority and current owners - -[ADR 0002](../adr/0002-cobra-backend.md) records the backend selection and rationale; -[ADR 0003](../adr/0003-public-facade.md) records its isolation behind the public -facade. The [architecture policy](../policy/architecture.md) owns boundaries. - -Cobra/pflag dependencies, the internal adapter, routing/parsing, generated help, -and invocation integration are implemented. Selected dependency versions belong -in [go.mod](../../go.mod); license and notice entries belong in -[attribution](../oss/attribution.md). The former dependency-selection and -adapter-construction tasks are complete. - -Current mechanics belong in the [internal overview](../internal/overview.md), -with adapter contracts and implementation in -[internal/cobra](../../internal/cobra/parse.go). The root owns registration, -typed input preparation, invocation coordination, standard handlers, and reports. -The [CLI reference](../cli.md) owns observable syntax and presentation. - -## Completed adaptation and evidence - -The initial implementation translated registered metadata through a neutral -bridge, rebuilt backend state for each invocation, and adapted backend routing, -local flags, operands, presence, help, and syntax failures to selected semantics. -The [completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -records these stages and their checks. - -The earlier discussion of rejecting repeated singletons was superseded by the -accepted last-occurrence rule in [ADR 0006](../adr/0006-command-grammar.md). -Detailed conversion, repetition, and terminator behavior belongs in -[registered command syntax](../cli.md#registered-command-syntax). - -The delivered integrations expose native ConfigKit/PromptKit reports through the -root, as recorded in the [feature target](initial.md). Backend selection creates -no parallel configuration engine or public backend-specific provider contract. -Completed parsing/help, provider integration, attribution, and evidence tasks -have been retired from this roadmap. - -## Future maintenance and adoption - -A later backend replacement remains a maintenance possibility governed by the -accepted public/CLI boundary and [release policy](../policy/release.md). A second -backend or generalized selection framework is outside the initial delivery. - -Application migrations and updates to their documentation/subprocess consumers -remain separate work. They can use the [consumer guide](../consumers/guide.md) -and maintained examples; this record does not claim migration completion. -Other deferred capabilities remain in the -[feature roadmap](initial.md#explicit-deferrals). diff --git a/docs/roadmap/04-facade.md b/docs/roadmap/04-facade.md deleted file mode 100644 index 5e3e9d7..0000000 --- a/docs/roadmap/04-facade.md +++ /dev/null @@ -1,56 +0,0 @@ -# CommandKit facade planning record - -Status: initial public facade and internal adapter implemented. - -Original planning: 2026-10-06. Reconciled: 2026-10-07. - -## Authority and current owners - -[ADR 0003](../adr/0003-public-facade.md) owns the facade/adapter decision and its -rationale. The [architecture policy](../policy/architecture.md) owns normative -dependency and public-surface boundaries. - -Root public declarations, private implementation state, and the internal -Cobra/pflag adapter exist. Exact contracts belong in Go declarations and GoDoc; -the [consumer guide](../consumers/guide.md) explains their use. The -[internal overview](../internal/overview.md) owns the actual package inventory, -and [go.mod](../../go.mod) owns dependency versions. - -The [initial target](initial.md) and [completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -record the chosen layout and delivered API work. The initial implementation -requires no further facade package construction. - -## Retired package exploration - -Early illustrations considered an `internal/engine` for registration and -coordination and an `internal/command` for shared declarations, with a root -limited mainly to forwarding. Those were possible layouts, not required -packages, and are superseded as active implementation targets. - -The selected root contains straightforward private implementation alongside its -public contracts; the internal adapter isolates backend machinery. Consult the -internal overview for current responsibilities instead of treating the early -package table as an inventory or expansion checklist. - -## Completed boundary work - -The initial work established root-owned public named types and handles, selected -integration dependencies, typed callback/value semantics, backend-neutral bridge -metadata/results, and adaptation of backend-owned failures. API design, -package-selection, and initial documentation tasks are complete. - -The completed plan records review of public declarations and dependency direction, -plus consumer behavior through the real adapter. Earlier suggestions to adopt -ConfigKit/ReleaseKit-style automated export scanners were validation possibilities, -not a requirement to add a checker. Future automation remains a maintenance -choice under the [testing policy](../policy/testing.md) when its protection -justifies its cost. - -## Future backend replacement - -A later replacement remains possible behind the accepted boundary. It must -preserve the public API and selected CLI behavior or follow the -[release policy](../policy/release.md) for deliberate incompatible changes. -Signature isolation alone does not prove behavioral compatibility; parsing, -help, diagnostic delivery, reports, and outcomes remain relevant to that review. -Replacement and public backend selection are outside the initial delivered scope. diff --git a/docs/roadmap/deferred.md b/docs/roadmap/deferred.md new file mode 100644 index 0000000..0b1f875 --- /dev/null +++ b/docs/roadmap/deferred.md @@ -0,0 +1,94 @@ +# Deferred work + +Status: retained future work and unselected proposals; no implementation schedule. + +## Purpose and authority + +Completed initial delivery, performance, ReleaseKit upgrade, and remediation +records have been retired. This document preserves their unfinished capability +targets and deferred ideas under the +[release policy](../policy/release.md#release-documentation-and-preparation). +The original records remain available in +[Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/6bc37e7ba64ca0920b4d0cc77039a18d4006b24e/docs/roadmap). + +Accepted [ADRs](../adr/) and the [architecture policy](../policy/architecture.md) +govern any future implementation. The [CLI reference](../cli.md), public GoDoc, +and [consumer guide](../consumers/guide.md) own implemented behavior. Retaining +an idea here does not select its syntax, API, priority, or delivery date. + +## Deferred capability targets + +### DIFF-01: semantic configuration comparison + +Expose comparison of two independently resolved selections of one scope using +owning-library safe snapshots. [ADR 0008](../adr/0008-semantic-configuration-diff.md) +owns the accepted comparison semantics, sensitivity union, and coverage-gap +handling. The target includes text/YAML reports of differences and gaps; +completed comparisons can succeed even when they find either. + +The initial review of ConfigKit v0.5.0 and PromptKit v0.12.0 did not find the +complete public snapshot/sensitivity contract needed for that target. Reassess +released upstream APIs when planning it; do not treat that historical review as +a claim about newer versions. Hidden-path metadata and supported gap reasons +must be available without fetching secrets. Rendered YAML and sibling internals +are not substitutes for an agreed public comparison representation. + +Comparison selection syntax, context inheritance, and report layout remain +future design work. Earlier possibilities included right-side root/overlay +selection, shared versus independent domain context, and an optional assertion +mode. Those choices are unselected. Add public types and handlers when the +capability is supported, rather than exposing placeholders. + +### CAT-01: PromptKit catalogs + +List captured prompt/version entries and named profiles through owning public +catalog APIs, with deterministic reports of loaded definitions. Resource names, +enumeration details, and report shapes remain future design work. + +The initial PromptKit v0.12.0 review did not find public enumeration APIs. +Reassess current released capabilities before planning delivery. Do not infer +catalogs by reparsing configuration YAML or inspecting sibling internals. + +## 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. +- Configuration mutation, generic value assignment, and exhaustive field-origin + inventories. +- Credential diagnostics and live provider probes. +- Additional component identity registration and domain artifact catalogs. +- Additional library families, including possible FeedKit integration; families + can define suitable verbs without requiring comparison or configuration scopes. +- Backend selection or replacement, a plugin framework, general dependency + injection, and concurrent-dispatch guarantees. + +Execution, rendering, serving, and session operations remain application-owned. +Shared vocabulary is guidance under [ADR 0006](../adr/0006-command-grammar.md). +Backend replacement remains possible behind the accepted facade, subject to the +published API/CLI contracts and deliberate compatibility decisions. + +## Possible further efficiency work + +Selected-scope memoization and selector-membership indexes were deferred pending +measurements that justify their bookkeeping. Mutable backend reuse across +invocations, segmented aggregate YAML delivery, provider caching, consumer-loader +redesign, and a replacement backend were outside the completed performance +target. Reconsider them only with concrete motivation and review of ownership, +invocation state, native reports, and the affected contracts. Retained measurement +records are historical evidence, not performance guarantees or release gates. + +## Consumer adoption and release preparation + +Consumer migrations remain separate from library delivery. Applications can +replace duplicated standard handlers and routing, then update their CLI docs +and subprocess consumers for intentional changes while retaining domain commands. +No migration order or claim about individual applications' adoption is recorded +here; the [consumer guide](../consumers/guide.md) and maintained examples provide +integration guidance. + +The next CommandKit release note must explain the Go 1.26.0 minimum and the +consumer action required by the ReleaseKit v0.3.0 upgrade. Version selection, +matching notes, and publication follow the [maintainer procedure](../release.md). +This cleanup does not select a release version or publish a release. diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md deleted file mode 100644 index 1ff45a9..0000000 --- a/docs/roadmap/implementation.md +++ /dev/null @@ -1,1027 +0,0 @@ -# Performance implementation plan - -Status: complete; Stages 1–11 are complete. - -Date: 2026-10-09. - -## Scope and authority - -Implement PF-01 through PF-06 from the [performance roadmap](performance.md). -Read this entire plan before starting and complete the numbered stages in order. -Each stage is a separate Luna implementation assignment and must leave the -repository buildable. The roadmap owns the target and selected OD-1/OD-2 -approaches; this plan owns execution choices, sequencing, and implementation -evidence. - -Follow the [architecture policy](../policy/architecture.md), accepted ADRs, -[agent policy](../policy/agents.md), [testing policy](../policy/testing.md), and -[documentation policy](../policy/documentation.md). Public Go declarations and -the [CLI reference](../cli.md) own existing contracts. Private names proposed -below identify implementation responsibilities, not new public APIs or durable -internal interfaces. - -This file replaces the completed ReleaseKit plan. Release tooling is already -implemented and is outside this sprint. Stage 11 repairs navigation that still -identifies this file as the ReleaseKit plan. The previous record is available -through Git history; do not restore its assignments here. - -No required product or architecture questions remain open. Measurements assess -the selected improvements; they do not authorize substituting persistent mutable -backends or segmented YAML delivery for the user's choices. - -## Baseline and implementation choices - -The planning baseline is `6612b54`, with a clean worktree. Production code still -matches the efficiency review at `54cfbd8`; intervening changes are documentation. -The root facade, internal Cobra adapter, inspection families, and release tooling -are implemented. No performance benchmarks were found in the indexed code, and -this planning pass has not executed tests, benchmarks, or profiles. Reinspect -current state before implementation and record the actual measurement revisions. - -Use the following concrete choices: - -- Render PromptKit's requested format in its handler, then pass completed bytes - to a shared delivery helper. Preserve the existing report DTOs and serializers. -- Index backend commands directly to neutral declarations. Walk Cobra's existing - parent links inside the adapter to reconstruct only the selected path. -- Scan YAML opening lines with byte offsets. Return complete framed bytes plus - whether the native document has directives, so the aggregate writer can use - one analysis. Retain the full framed buffer selected in OD-2. -- Prepare and clone pending command registrations before updating the existing - registry. Keep batch validation atomic and preserve owned declaration storage. -- Lazily cache one neutral bridge tree per `App`, invalidating it after a - successful nonempty registration. Construct fresh mutable backend state for - each invocation, then reuse it for parsing, help, and usage within that - invocation, as selected in OD-1. -- Represent registered configuration metadata with a private generic prepared - suite containing normalized declarations, ordered scopes, name lookup, and - discovery inventory. Use name/short-name maps for selector duplicate checks. - Keep scope selection in preflight and handlers as inexpensive indexed passes. - Selected-scope memoization and additional selector-membership indexes are - deferred; their mutable bookkeeping is unnecessary for removing the observed - quadratic scope searches. - -PF-05 and the bounded PF-06 changes above are included in the sprint despite their -lower priority. Implement the straightforward algorithms and measure their cost; -do not silently omit either coverage ID. Escalate concrete correctness conflicts -or material regressions rather than add a new consumer restriction or change -the selected scope. - -## Instructions for every stage - -1. Start with [developer orientation](../development.md), inspect Git state, and - read the assigned sources and prior stage evidence. Prefer knowledge-graph - tools for code discovery. Preserve unrelated work and read applicable policies. -2. Implement the assigned stage and necessary supporting tests/documentation. - Preserve public signatures and the fields of value structs such as - `Invocation`, `CommandSpec`, and `ConfigSuite`; do not add execution state to - them. The `App` handle may gain private implementation fields. Cobra/pflag - objects and errors stay inside their adapter. -3. Preserve grammar, conversion of every supplied singleton occurrence, explicit - presence, collection ownership, callback lifecycle, supported error identity, - diagnostic delivery, and report semantics. Reuse existing coverage; add only - missing protection for the change's realistic risks. Do not assert private - helper counts or fixed timings in behavioral tests. -4. Format changed Go files. Run the stage's focused validation and measurements. - Dependency preparation, if needed, is separate from offline measurement. - Apply the measurement protocol's workspace, local-toolchain, and offline - environment settings to Go validation commands as well. - Tests and benchmarks added by this plan are development evidence, not new - release gates. Leave the opt-in ReleaseKit publication exercise unselected. -5. Record actual commands, results, fixture dimensions, relevant comparisons, - and unresolved issues in the stage's evidence field. Never replace pending - evidence with an expected result. Investigate a regression before proceeding; - absence of a timing speedup is not permission to invent a faster contract. -6. Review staged changes and commit each completed stage under the agent policy. - Report its commit, checks, and remaining work. Proceed only when its completion - conditions hold. Update the roadmap's overall status when implementation - begins and ends; detailed execution results belong here. - -No concurrency guarantee, public freeze step, new parser, provider cache, library -version change, or release publication is needed. Application callbacks retain -their effects. Do not forbid registration from callbacks to simplify caching; -refresh metadata-dependent presentation when successful registration has made -the invocation's prepared metadata stale, without repeating input callbacks. - -## Measurement protocol - -Use standard Go benchmarks named with prefix `BenchmarkPerformance`. Use the -same fixtures and measurement scope before and after a change. Record Go version, -GOOS/GOARCH, CPU/machine description, source revision, and fixture dimensions. -Separate app construction plus first execution from execution on an existing -app. Exclude fixture construction from repeated-execution measurements and include -it only when explicitly measuring construction/registration. - -Use in-memory provider fixtures and `io.Discard` for ordinary delivery -measurements. Observe outcomes so invalid fixtures cannot appear as fast success. -Actual ConfigKit/PromptKit loading is covered by existing integration tests; -these measurements isolate CommandKit overhead and do not contact providers. -Keep a few representative shapes rather than a Cartesian product of dimensions. - -With module caches prepared, the common measurement command is: - -```sh -GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformance' -benchmem -benchtime=200ms -count=5 . ./internal/cobra -``` - -Narrow `-bench` and the package list for each stage. Save raw output outside the -worktree and summarize representative ns/op, B/op, and allocs/op results here, -including variation or inconclusive differences. When measurements span a -different machine or Go version, repeat the baseline in an isolated checkout -with the same benchmark sources before making a timing claim. Profile CPU or -allocations only when needed to explain a remaining cost or regression. No new -benchmark-analysis dependency or permanent numeric pass threshold is selected. - -## Stage inventory - -| Stage | Deliverable | Roadmap coverage | -| --- | --- | --- | -| 1 | Dispatch and registration baseline benchmarks | PF-02, PF-03, PF-05 | -| 2 | Inspection and scope baseline benchmarks | PF-01, PF-04, PF-06 | -| 3 | PromptKit rendering for the selected format | PF-01 | -| 4 | Direct declaration lookup and ancestry traversal | PF-02 | -| 5 | YAML preamble analysis with complete framed delivery | PF-04, OD-2 | -| 6 | Registration without copying existing entries | PF-05 | -| 7 | Cached immutable bridge metadata | PF-03, OD-1 | -| 8 | An invocation-owned adapter session | PF-03, OD-1 | -| 9 | Root dispatch, help, and usage integration | PF-03, OD-1 | -| 10 | Prepared configuration suite metadata | PF-06 | -| 11 | Final behavioral/performance audit and documentation | PF-01–06 | - -## Stage 1: establish dispatch and registration measurements - -**Status:** complete. **Prerequisite:** orientation and this plan. - -**Files:** new `performance_dispatch_test.go`, -`internal/cobra/performance_test.go`, and evidence here. Production code stays -unchanged in this stage. - -1. Create small test-only command fixtures: a small flat registry with 8 custom - commands, a wide registry with 128 custom commands, and a nested path of - depth 24 with sibling commands. Add one flag-heavy leaf case with 24 flags. - These dimensions are benchmark inputs, not supported-size limits. -2. Add root benchmarks for repeated success, local `--help`, explicit - `help COMMAND`, parser usage failure, and handler-returned usage. Use the - small fixture for the full path set and the wider/deeper fixtures for success - and help. Add construction plus first-execution cases for small and wide apps. - Use real routing and bindings with a cheap typed handler and stable streams. -3. Add adapter `Parse` benchmarks for shallow/wide and deep neutral trees to - isolate PF-02 from root report work. Keep the neutral declarations outside - the timed region; include backend construction in the `Parse` measurement. -4. Add registration benchmarks comparing individual and batch registration of - 8 and 128 preconstructed declarations. Include fresh `New` plus registration - in both timed paths so the comparison has the same construction overhead. -5. Run and record the baseline under the measurement protocol. Preserve benchmark - inputs for subsequent stages. Verify setup and expected outcome classes; - fix the fixture if it unexpectedly measures an error path. - -**Validation:** compile both packages with `go test -mod=readonly -run '^$' -. ./internal/cobra`, then execute the new benchmarks. No timing assertions, -production instrumentation, or full dependency test matrix is needed. - -**Completion:** reproducible baseline results distinguish registration, cold -execution, repeated execution, parsing, and help/usage costs. - -**Evidence:** Benchmark fixtures were measured from source revision `1274ae7` -with the new benchmark files in the working tree (committed with this evidence). -Environment: Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz. The required compile-only command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' . ./internal/cobra`. -The five-sample measurement command also passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformance' -benchmem -benchtime=200ms -count=5 . ./internal/cobra`. -Raw output is in `/tmp/commandkit-performance-baseline.txt`; focused repeat output -for noisy cases is in `/tmp/commandkit-performance-baseline-repeat.txt`. - -Fixtures: root dispatch used 8 and 128 flat commands, a 24-level path with -siblings at each parent, and a leaf with 24 flags. Dispatch covered success, -local and explicit help, parser and handler usage, cold construction plus first -execution, and repeated execution. Registration used 8 and 128 prebuilt -declarations with fresh `New` in individual and batch paths. Adapter parsing -used 128 shallow siblings and the same depth-24 path. All repeated app and -adapter fixtures were built outside the timed loops; benchmark outcomes were -checked for their intended classes. - -Representative five-sample ranges (ns/op; B/op; allocs/op): small repeated -success 31,066–41,041; 33,209–33,210; 287. Small local help 103,022–116,183; -78,176–78,177; 810. Parser usage 62,596–74,475; 66,363–66,364; 591. Wide -success 218,073–253,010; 269,063–269,070; 1,898. Deep success 119,958–139,625; -139,787–139,791; 1,074. Wide help 491,172–622,188; 549,923–549,940; 4,033. -Explicit help measured 101,998–111,895 ns/op, 78,152–78,153 B/op, and 815 -allocs/op; handler usage measured 61,878–72,264 ns/op, 66,211–66,212 B/op, and -583 allocs/op. Cold construction plus first execution measured 38,152–50,235 -ns/op, 38,275–38,276 B/op, and 339 allocs/op for the small app, and -251,945–315,276 ns/op, 291,822–291,827 B/op, and 2,184 allocs/op for the wide -app. The 24-flag leaf focused repeat was 43,662–56,492 ns/op, 40,027–40,028 -B/op, and 401 allocs/op. -Deep help was noisy in the full run (429,873–1,634,363 ns/op); a focused repeat -was 300,155–326,094 ns/op, 294,882–294,896 B/op, and 2,408 allocs/op. The initial -flag-heavy timing also varied widely before the focused range reported above. -Registration at 8 declarations measured individual 7,141–7,645 ns/op, -5,497 B/op, 64 allocs/op versus batch 4,159–5,190 ns/op, 3,456 B/op, -48 allocs/op. At 128 declarations, individual measured 414,618–492,261 ns/op, -405,011–405,018 B/op, 784 allocs/op versus batch 33,985–36,207 ns/op, -23,013–23,014 B/op, 288 allocs/op. Adapter parse measured shallow/wide -150,918–171,598 ns/op, 242,936 B/op, 1,705 allocs/op, and deep -86,282–109,697 ns/op, 119,920 B/op, 827 allocs/op. These are baselines, not -speedup claims; the large initial deep-help and flag-heavy timing variation -shows why later comparisons should report run variation. - -## Stage 2: establish report and scope measurements - -**Status:** complete. **Prerequisite:** Stage 1. - -**Files:** new `performance_reports_test.go` and evidence here. Production code -stays unchanged in this stage. - -1. Use direct `PromptKitSuite` callbacks returning fixed inspection records. - Measure prompt text/YAML with 4 and 128 inputs, and profile text/YAML with - small and larger nested `ExtraParams` maps. Construct fixtures outside the - timed loop; use `App.Execute` so parsing and delivery are represented. -2. Add isolated framing and aggregate `config show --scope all` benchmarks with - two native document fixtures: approximately 4 KiB and 1 MiB with many short - lines. Keep native content and provider callbacks fixed. Include an ordinary - preamble and a directive-bearing preamble, without multiplying every size by - every marker variation. Measure single-scope display as a reference case. -3. Measure `config scopes`, named selection, and aggregate validation with 2 and - 32 scopes. Give every aggregate fixture the requested capability and use cheap - acquisition callbacks. Add suite registration with 4 and 64 distinct selectors - to expose duplicate-check cost without using duplicate declarations. -4. Run and record these baselines before handler or scope changes. Label isolated - helper results separately from complete command execution. Adjust internal - benchmark calls after later signature refactors only as necessary to measure - the same logical operation and fixtures. - -**Validation:** compile the root package and run the new report/scope benchmarks -under the common protocol. Confirm the fixtures produce the intended formats and -success outcomes outside timed setup; existing integration coverage remains the -owner of actual library loading semantics. - -**Completion:** PF-01, PF-04, and PF-06 have comparable baseline measurements. - -**Evidence:** Fixtures were measured from source revision `aed4c59` with -`performance_reports_test.go` in the working tree (committed with this evidence). -Environment matched the first baseline: Go 1.26.8, linux/amd64, Linux -6.17.0-41-generic, Intel Core i5-7260U CPU @ 2.20 GHz. Root package compilation -passed with `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' .`. The five-sample benchmark command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformance(PromptReports|YAMLFraming|ConfigScopes|ConfigRegistration)$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-reports-baseline.txt`. - -Fixtures: PromptKit callbacks returned prebuilt inspection records directly; -prompt reports used 4 and 128 input records, while profile `ExtraParams` used -2 groups with 3 nested values each or 24 groups with 8 nested values each and a -nested sequence. Each was measured as text and YAML through `App.Execute`. -Native YAML fixtures contain unique short mapping keys and are 4,096 bytes with -an ordinary comment preamble and 1,048,591 bytes with a `%YAML` directive -preamble. Framing was measured directly; aggregate `config show --scope all` -measured two documents of each selected fixture size/style, and single-scope -display used the 4 KiB ordinary document. Scope operations used 2 or 32 scopes -with the requested show/validate capabilities and cheap in-memory acquisition -callbacks. Suite registration used 4 or 64 distinct selectors and a fresh app. -The scope counts also covered discovery, named validation, and aggregate -validation. Setup verified success and report shape outside timed loops; native -fixtures, records, suites, and apps were prepared outside repeated loops. - -Representative five-sample ranges (ns/op; B/op; allocs/op): prompt, 4 inputs, -text 41,287–52,115; 26,160–26,161; 294, and YAML 88,991–104,671; -74,730–74,733; 557. Prompt, 128 inputs, text 169,155–198,281; -145,524–145,531; 1,171, and YAML 1,418,692–1,490,181; 1,393,508–1,393,568; -6,039–6,040. Profile, small extra map, text 74,109–89,337; 70,914–70,918; -462, and YAML 161,470–368,813; 162,688–162,717; 755. Profile, large extra map, -text 1,277,396–2,583,950; 836,141–836,296; 3,027–3,028, and YAML -1,756,571–2,377,499; 1,586,728–1,586,849; 5,878–5,879. Larger profile timings -varied, while allocation counts and bytes were stable. - -Direct framing measured 4 KiB ordinary at 5,883–6,842 ns/op, 11,056 B/op, -3 allocs/op, and 1 MiB directive at 1,208,678–1,502,417 ns/op, -2,539,520–2,539,523 B/op, 2 allocs/op. Aggregate show measured 4 KiB documents -at 44,395–48,161 ns/op, 55,537–55,538 B/op, 211 allocs/op, and 1 MiB documents -at 4,818,907–6,009,877 ns/op, 8,695,182–8,695,197 B/op, 215–216 allocs/op. -Single-scope 4 KiB display measured 20,229–21,791 ns/op, 17,935–17,936 B/op, -183 allocs/op. With 2 scopes, discovery measured 23,840–30,007 ns/op, -21,161–21,162 B/op, 223 allocs/op; named validation 24,841–26,340 ns/op, -21,817 B/op, 228 allocs/op; aggregate validation 25,231–31,126 ns/op, -22,361–22,362 B/op, 237 allocs/op. With 32 scopes, discovery measured -31,439–37,167 ns/op, 28,141–28,142 B/op, 257 allocs/op; named validation -29,123–74,374 ns/op, 22,775–22,778 B/op, 228 allocs/op; aggregate validation -45,548–63,471 ns/op, 29,781–29,782 B/op, 269 allocs/op. Registration with 4 -selectors measured 12,573–14,789 ns/op, 8,911 B/op, 104 allocs/op; with 64 it -measured 91,675–105,548 ns/op, 82,817–82,818 B/op, 485 allocs/op. Large-report -cost includes full output framing/delivery; no segmented-delivery comparison -was selected. These measurements establish baselines and show timing variation; -they are not fixed thresholds or speedup claims. - -## Stage 3: render only the selected PromptKit format - -**Status:** complete. **Prerequisite:** Stage 2. - -**Files:** [promptkit.go](../../promptkit.go), -[promptkit_test.go](../../promptkit_test.go), relevant report benchmarks, and -evidence here. - -1. In `runPromptKitPrompt` and `runPromptKitProfile`, select YAML or text before - calling either text formatter. Preserve report DTO construction and all - acquisition, cancellation, nil-result, and diagnostic handling. -2. For YAML, encode into a `bytes.Buffer` and use its bytes directly. For text, - format once and convert the completed string to bytes without copying it - through an additional builder. Preserve profile text-formatting errors. -3. Reduce `writePromptKitReport` to shared delivery of completed bytes plus - diagnostics. Keep the pre-delivery cancellation check, checked writer, and - incomplete-report outcome handling. Both formats finish rendering before - this delivery step. No lazy public formatter API is needed. -4. Reuse the real inspection tests for report fields, input order, nil parameter - maps, nested `ExtraParams`, cancellation, and output failures. Add focused - missing cases rather than collaborator-call assertions or broad snapshots. -5. Rerun prompt/profile measurements and compare them with Stage 2. Explain any - text-path regression or unexpectedly unchanged YAML allocation result. - -**Validation:** root PromptKit inspection and cancellation tests, followed by -the applicable report benchmarks. Use `go test -mod=readonly -count=1 .` for -root behavioral validation. Preserve public error identity and existing -report confidentiality; this change introduces no redaction policy. - -**Completion:** YAML requests do not construct text reports, and text delivery -has no redundant intermediate builder. - -**Evidence:** `go test -mod=readonly -count=1 .` passed with the workspace, -local toolchain, and offline environment settings from the measurement protocol. -The same five-sample report fixtures passed with: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformancePromptReports$' -benchmem -benchtime=200ms -count=5 .`. -The environment matched Stage 2: Go 1.26.8, linux/amd64, Linux -6.17.0-41-generic, Intel Core i5-7260U CPU @ 2.20 GHz. The measured source was -revision `a431540` plus the `promptkit.go` working-tree change committed with -this evidence. Raw output is in `/tmp/commandkit-performance-prompt-after.txt`. - -Every five-sample report case reduced allocation count. Prompt, 4 inputs, text -changed from 41,287–52,115 ns/op, 26,160–26,161 B/op, 294 allocs/op to -29,898–35,259 ns/op, 25,280–25,282 B/op, 291 allocs/op; YAML changed from -88,991–104,671 ns/op, 74,730–74,733 B/op, 557 allocs/op to 83,454–91,286 -ns/op, 71,853–71,855 B/op, 505 allocs/op. Prompt, 128 inputs, text changed -from 169,155–198,281 ns/op, 145,524–145,531 B/op, 1,171 allocs/op to -161,185–185,023 ns/op, 128,960–128,966 B/op, 1,168 allocs/op; YAML changed -from 1,418,692–1,490,181 ns/op, 1,393,508–1,393,568 B/op, 6,039–6,040 -allocs/op to 1,255,623–1,360,926 ns/op, 1,264,474–1,264,486 B/op, 5,104 -allocs/op. - -Profile, small extra map, text changed from 74,109–89,337 ns/op, -70,914–70,918 B/op, 462 allocs/op to 75,818–88,197 ns/op, 69,955–69,959 -B/op, 459 allocs/op; the timing ranges overlap. YAML changed from -161,470–368,813 ns/op, 162,688–162,717 B/op, 755 allocs/op to 107,244–127,744 -ns/op, 114,793–114,795 B/op, 533 allocs/op. Profile, large extra map, text -changed from 1,277,396–2,583,950 ns/op, 836,141–836,296 B/op, 3,027–3,028 -allocs/op to 839,692–936,229 ns/op, 826,407–826,448 B/op, 3,024 allocs/op; -YAML changed from 1,756,571–2,377,499 ns/op, 1,586,728–1,586,849 B/op, -5,878–5,879 allocs/op to 796,779–976,685 ns/op, 780,391–780,436 B/op, -3,086 allocs/op. These results confirm that YAML requests avoid text-report -construction; text requests retain their report semantics and formatting errors. - -## Stage 4: index backend declarations and traverse parents - -**Status:** complete. **Prerequisite:** Stage 3. - -**Files:** [adapter](../../internal/cobra/parse.go), -[adapter tests](../../internal/cobra/parse_test.go), relevant benchmarks, and -evidence here. - -1. Change the construction index to map backend command pointers directly to - neutral declarations. Update `Parse`, `RenderHelp`, and `UsageLine` to use - direct lookup instead of scanning declaration-to-backend entries. -2. Reconstruct a selected path by walking the backend's `Parent()` links and - reading each mapped declaration's name, excluding the root. Reverse the - collected names once. Remove recursive root-based parent discovery. -3. Keep neutral failures for missing trees/unmapped selections and exact-path - verification. Do not rely on Cobra prefix matching to define accepted paths. -4. Extend adapter coverage only where needed for a deep path, wide siblings, - unknown paths, root selection, and help/usage path resolution. Existing - parsing and flag-state tests remain applicable. -5. Compare adapter and complete dispatch benchmarks with Stage 1. The tree still - rebuilds here; distinguish reduced path-search cost from that remaining cost. - -**Validation:** `go test -mod=readonly -count=1 ./internal/cobra .`, then the applicable -parse and dispatch benchmarks. - -**Completion:** declaration lookup uses the index and ancestry traversal is -proportional to selected depth after backend construction. - -**Evidence:** `go test -mod=readonly -count=1 ./internal/cobra .` passed with -the common offline environment settings. The focused test covers a 24-level -path, 128 siblings, root selection, unknown help/usage paths, and exact help and -usage resolution. Existing exact-path and parse failure tests remain in place. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `628dc78` with this stage's -changes in the working tree. The five-sample adapter command was -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformanceParse$' -benchmem -benchtime=200ms -count=5 ./internal/cobra`; -the dispatch command used the same flags with `-bench -'^BenchmarkPerformanceDispatch$' .`. Both passed. Raw outputs are in -`/tmp/commandkit-performance-parse-after-stage4.txt` and -`/tmp/commandkit-performance-dispatch-after-stage4.txt`. - -Adapter shallow/wide Parse measured 149,426–171,199 ns/op, -242,936 B/op, and 1,705 allocs/op, compared with baseline 150,918–171,598 -ns/op, 242,936 B/op, and 1,705 allocs/op. Deep Parse measured 90,608–104,770 -ns/op, 119,536 B/op, and 826 allocs/op, compared with baseline 86,282–109,697 -ns/op, 119,920 B/op, and 827 allocs/op. Timings overlap; deep parsing saves -384 B and one allocation. End-to-end dispatch allocations remain effectively -unchanged across the measured cases. Timing variation, including deep-help -outliers, is substantial, so these runs do not support an end-to-end speedup -claim. The comparison isolates the selected-path lookup change while backend -tree construction remains in each parse. - -## Stage 5: scan YAML preambles without splitting documents - -**Status:** complete. **Prerequisite:** Stage 4. - -**Files:** [show.go](../../show.go), [show_test.go](../../show_test.go), -[configkit_test.go](../../configkit_test.go), framing benchmarks, and evidence. - -1. Introduce a private preamble analysis using `bytes.IndexByte` to locate line - boundaries and byte trimming for classification. Track marker positions, - preamble end, directives, and inline marker content. Stop when the opening - framing decision is complete. Preserve Unicode whitespace behavior and - accepted space/tab marker forms; do not add a general YAML parser or limits. -2. Have `frameEffectiveYAML` return complete framed bytes and a directive flag - from that analysis. Update its internal callers/tests for the result pair. - Remove the independent full-document split in `hasYAMLDirective` and use the - same analysis for aggregate completion-marker decisions. -3. Retain the complete native buffer and framed buffer per document. Preserve - placement of labels around inline content/block scalars, authored comments, - directives, native byte slices, quoted scope labels, and boundary newlines. - Keep the existing aggregate document-end marker where directives require it. -4. Leave acquisition-before-output, direct single-scope writing, cancellation - boundaries, and write-error outcomes intact. Do not introduce segmented native - delivery, indentation wrappers, or reserialization of provider documents. -5. Reuse `TestEffectiveYAMLFramingPreservesOneNativeDocument` and aggregate - acquisition/delivery tests. Fill meaningful gaps for absent trailing newline, - CRLF, directive preambles, and control characters in labels. Verify native - content preservation as well as decoded values and document count. -6. Compare framing/aggregate measurements with Stage 2, emphasizing allocation - growth with line count. Report the full framed copy as an intentional retained - cost under OD-2. - -**Validation:** root framing/configuration behavior with -`go test -mod=readonly -count=1 .`, then the relevant report benchmarks. - -**Completion:** each document has one opening analysis, no document-wide line -index, and the selected complete-buffer delivery model. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 .` passed. Existing aggregate tests -continue to cover acquisition-before-output, directive document separators, -decoded values, diagnostics, and writer failures. New framing cases cover a -missing final newline, CRLF, a directive preamble, a control character in the -scope label, unchanged native bytes, decoded values, and one-document output. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `ae656d8` with this stage's -changes in the working tree. The five-sample command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformanceYAMLFraming$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-yaml-after-stage5.txt`. - -Direct 4 KiB ordinary framing measured 1,135–1,455 ns/op, 4,864 B/op, and one -allocation, compared with 5,883–6,842 ns/op, 11,056 B/op, and three allocations -at baseline. Direct 1 MiB directive framing measured 189,303–359,655 ns/op, -1,056,768–1,056,769 B/op, and one allocation, compared with 1,208,678–1,502,417 -ns/op, 2,539,520–2,539,523 B/op, and two allocations. Aggregate 4 KiB show -measured 29,951–49,108 ns/op, 36,999–37,001 B/op, and 206 allocations, compared -with 44,395–48,161 ns/op, 55,537–55,538 B/op, and 211 allocations. Aggregate -1 MiB show measured 1,326,104–1,557,880 ns/op, 4,246,730–4,246,767 B/op, and -211 allocations, compared with 4,818,907–6,009,877 ns/op, 8,695,182–8,695,197 -B/op, and 215–216 allocations. Single-scope 4 KiB display remained at -17,935–17,936 B/op and 183 allocations; timing variation overlaps the baseline. -The complete framed output still requires a full-size copy under OD-2. The -allocation reduction comes from eliminating document-wide split/index storage -and reusing the opening analysis for framing and aggregate directive handling. - -## Stage 6: install validated registrations without copying the registry - -**Status:** complete. **Prerequisite:** Stage 5. - -**Files:** [registry.go](../../registry.go), -[registry_test.go](../../registry_test.go), registration benchmarks, and evidence. - -1. Preserve the nil-app check. Validate each declaration and check its name - against both existing registrations and pending entries. Clone declarations - into private pending storage before modifying the app. -2. After the whole batch succeeds, initialize the app's map if needed and add - the pending entries to it. Leave existing entries untouched. An empty batch - remains a successful no-op on a non-nil app. -3. Preserve batch failure behavior for invalid later declarations, duplicates - within a batch, existing paths, and reserved help/version paths. Keep existing - cloning boundaries rather than sharing caller-owned child slices. -4. Reuse atomicity and callback-free registration tests. Add a missing late-failure - or within-batch collision case only if existing coverage is insufficient. -5. Compare individual/batch registration with Stage 1. Sorting and metadata - preparation remain separate until Stage 7. - -**Validation:** registry/declaration behavior with -`go test -mod=readonly -count=1 .`, then registration benchmarks. - -**Completion:** registration copies only pending declarations and preserves -all-or-nothing validation without rebuilding the existing registry map. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 .` passed. Existing tests cover -atomic rollback, reserved paths, callback lifecycle, and ownership. Added a -duplicate-within-batch case and confirmed that it leaves the registry unchanged. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `3f8841f` with this stage's -changes in the working tree. The five-sample command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformanceRegistration$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-registration-after-stage6.txt`. - -At 8 declarations, individual registration measured 4,873–5,401 ns/op, -3,152 B/op, and 45 allocations; batch registration measured 4,404–10,155 ns/op, -3,152 B/op, and 45 allocations (the timing range includes noisy outliers). -At 128 declarations, individual registration measured 55,274–64,107 ns/op, -29,399–29,400 B/op, and 293 allocations, compared with the Stage 1 baseline -414,618–492,261 ns/op, 405,011–405,018 B/op, and 784 allocations. Batch -registration measured 47,867–53,858 ns/op, 35,969–35,970 B/op, and 296 -allocations, compared with baseline 33,985–36,207 ns/op, 23,013–23,014 B/op, -and 288 allocations. A slice-only pending check reduced the batch allocation -cost to about 30.5 KB but was slower (about 61–66 μs) because it scans pending -names quadratically; the map-based pending index is retained for linear-time -duplicate validation. The batch regression remains measurable and reflects -growing the existing map plus maintaining pending entries; restoring a full -registry rebuild would contradict this stage's selected change. Individual -registration has a large allocation and latency reduction. No correctness -issues remain open. - -## Stage 7: cache immutable bridge metadata per app - -**Status:** complete. **Prerequisite:** Stage 6. - -**Files:** [app.go](../../app.go), [parser.go](../../parser.go), registry invalidation, -root parser/registry tests, dispatch benchmarks, and evidence. - -1. Add a private cached neutral tree pointer to `App`. Split bridge translation - into a cache accessor and an uncached builder. Build lazily on first use; - sort root names and child lists once per registry state while creating owned - flag/operand metadata. The cached neutral tree is read-only thereafter. -2. Invalidate the pointer at successful nonempty registration's completion point. - Failed and empty registrations retain valid cached metadata. Built-in - construction remains before first use; do not create metadata eagerly for - each individual command registration. -3. Keep this cache free of contexts, streams, parsed values, provider views, and - Cobra/pflag objects. Adapter construction reads the neutral tree without - mutating it. A pointer to the neutral tree identifies a prepared metadata - generation for Stage 9, avoiding a separate counter. -4. Protect observable behavior after success, failure, and empty registration - following earlier execution/help. Check that newly installed configuration - and PromptKit families appear after an earlier help request without provider - loading. Preserve owned declarations and sorted metadata. -5. Compare cold and repeated execution with Stage 1. Account for the one retained - neutral tree per app and confirm rebuilding occurs only when needed through - source review and measurements, not public allocation/count assertions. - -**Validation:** root registry/parser/help tests and dispatch benchmarks. Each -invocation still creates fresh backend values at this stage. Use -`go test -mod=readonly -count=1 .` for root behavioral validation. - -**Completion:** unchanged registrations reuse translated metadata; successful -registration is visible to later parsing and help. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 .` passed. The new behavioral test -builds help metadata, registers a command and both standard command families, -then confirms later help and parsing see them without invoking provider -callbacks. It also checks visibility after failed and empty registration. -Source review confirms the tree is built lazily, contains only neutral -declarations/flag/operand metadata, and is cleared only after successful -nonempty registration. Root and child ordering is performed by the uncached -builder once per metadata generation. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `5816dd3` with this stage's -changes in the working tree. The five-sample command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformanceDispatch$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-dispatch-after-stage7.txt`. - -Repeated small success changed from 31,066–41,041 ns/op, 33,209–33,210 B/op, -and 287 allocations to 26,008–31,223 ns/op, 29,408–29,409 B/op, and 267 -allocations. Wide success changed from 218,073–253,010 ns/op, 269,063–269,070 -B/op, and 1,898 allocations to 182,431–194,243 ns/op, 247,626–247,635 B/op, -and 1,756 allocations. Deep success changed from 119,958–139,625 ns/op, -139,787–139,791 B/op, and 1,074 allocations to 103,208–124,879 ns/op, -124,240–124,242 B/op, and 879 allocations. Help and usage paths also reduced -allocations and bytes. Cold construction plus first execution remained similar -for the small app (38,152–50,235 ns/op, 38,275–38,276 B/op, 339 allocations -baseline; 39,158–47,365 ns/op, 38,243 B/op, 338 allocations now). The wide -cold case changed from 251,945–315,276 ns/op, 291,822–291,827 B/op, and 2,184 -allocations to 271,403–321,746 ns/op, 305,046–305,051 B/op, and 2,194 -allocations. Its timing range overlaps baseline; the extra cold storage is the -retained neutral tree. The measured tradeoff is lower repeated-execution cost -with one tree allocation retained per app metadata generation. - -## Stage 8: introduce an invocation-owned adapter session - -**Status:** complete. **Prerequisite:** Stage 7. - -**Files:** the adapter, its tests/benchmarks, and evidence. Root execution remains -functional through the existing package-level adapter helpers during this stage. - -1. Add an internal `Session` handle with private backend root, neutral metadata, - and reverse declaration index. Use `Prepare(*Command, ParseOptions) *Session`; - construction normalizes options and builds a fresh mutable tree. A missing - tree is represented by a session whose operations return neutral failures. - Methods are `Parse([]string) Result`, `RenderHelp([]string) (string, *Failure)`, - and `UsageLine([]string) (string, *Failure)`. They expose no backend types. -2. Move existing parse/help/usage logic into those methods. Reuse the prepared - tree and Stage 4's index/path traversal. Help renders to a private buffer; - temporarily redirect and restore the selected backend's output/error streams - so generated bytes remain under root delivery control. -3. Keep package-level helpers as thin one-session conveniences for current root - calls and focused adapter benchmarks/tests. They must delegate to the same - methods, not maintain parallel parsing or help implementations. -4. Keep malformed/nil-tree results neutral. Metadata remains read-only; parsed - values belong to the session. Test parse followed by help and usage on one - session, and fresh values/streams on separately prepared sessions. Do not - add a public session API, pool, persistent backend cache, or reset framework. -5. Add a small parse-plus-help session benchmark using an existing fixture. - Label it as a new internal measurement; existing end-to-end benchmarks are - still the before/after evidence for root integration in Stage 9. - -**Validation:** `go test -mod=readonly -count=1 ./internal/cobra .`, then adapter benchmarks. - -**Completion:** the adapter can perform parsing and metadata presentation on -one prepared invocation tree while legacy root entry points still compile. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 ./internal/cobra .` passed. Added -coverage for parse followed by help and usage on one session, fresh mutable -values and streams across separately prepared sessions, and neutral failures -for missing trees. Help output is captured and the selected command's original -streams are restored. Existing exact-path, parse-failure, and flag-state tests -continue to pass. The package-level helpers now each prepare one session and -delegate to its method. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `3ad3559` with this stage's -changes in the working tree. The five-sample adapter command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformance(Parse|SessionParseAndHelp)$' -benchmem -benchtime=200ms -count=5 ./internal/cobra`. -Raw output is in `/tmp/commandkit-performance-adapter-after-stage8.txt`. - -The new parse-plus-help session benchmark, with an 8-sibling tree prepared -outside the timed loop, measured 33,456–50,352 ns/op, 10,658 B/op, and 226 -allocations. The existing shallow/wide Parse wrapper measured 242,952–242,956 -B/op and 1,706 allocations; deep measured 119,552–119,553 B/op and 827 -allocations. Compared with the Stage 4 adapter baseline, each adds 16 bytes and -one allocation for the one-session wrapper. Timings ranged widely in this run, -so they are inconclusive; tree construction remains included in these wrapper -benchmarks. The session benchmark excludes its one-time tree preparation and -measures repeated parse plus help on the same fresh-per-session backend state. - -## Stage 9: reuse the adapter session throughout root execution - -**Status:** complete. **Prerequisite:** Stage 8. - -**Files:** [execute.go](../../execute.go), [builtins.go](../../builtins.go), -private parser coordination, [execute_external_test.go](../../execute_external_test.go), -dispatch benchmarks, and evidence. - -1. Introduce private execution coordination local to `App.Execute`, retaining - the app, parse options, neutral tree pointer, and session. Prepare after the - existing context/stream checks. Keep early nil-app/context outcomes and - generic usage fallbacks functional without a usable session. -2. Route parse, root/group/local help, usage after parse/input failures, and - usage returned by handlers through that local coordination. Keep the existing - input preparation and callback order, including supplied-value validation - for help. Normal domain handlers still receive the public `Invocation`. -3. Handle the reserved top-level `help` command explicitly in the dispatcher - after its ordinary typed preparation/checks: use its private `helpInput`, - resolve the target with `helpCommandTarget`, and render through the local - session. Share target/render logic with its registered built-in handler. - A one-off private convenience may prepare a session for direct internal - helper calls; the `Execute` path must use its existing session. Preserve - runnable help metadata and the semantics of `help --help` and unknown targets. -4. Do not store the active session on `App`, add it to public `Invocation`, or - put it in caller contexts. For help/usage presentation, compare the current - cached metadata pointer with the session's pointer. If successful registration - by a callback changed metadata, prepare presentation against the new tree - without rerunning parsing, factories, checks, or handlers. This preserves - registration freedom without caching stale presentation. -5. Preserve outcome normalization, cause/error identity, diagnostic ownership, - delivery errors, and incomplete-report reporting. Remove obsolete duplicate - preparation paths once all root execution branches are integrated. -6. Reuse the existing help-entry and fresh-invocation tests. Fill gaps for a - successful flag-bearing invocation followed by help and omitted/false/empty - values, distinct streams/contexts, handler usage, and registration followed - by metadata presentation. Test contracts, not exact session-construction counts. -7. Compare complete help/error/repeated/cold execution with Stage 1. Stable - metadata should need one backend preparation through each ordinary invocation, - including explicit `help`; verify structurally and through measurements. - -**Validation:** root dispatcher/help/outcome/cancellation tests, adapter tests, -with `go test -mod=readonly -count=1 . ./internal/cobra`, then complete dispatch -benchmarks. Use existing facade boundary coverage/review -to confirm that signatures and backend isolation are unchanged. - -**Completion:** every normal `Execute` path uses the selected OD-1 lifecycle and -all existing public handler and presentation semantics remain intact. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 ./internal/cobra .` passed. Existing -help, parser, outcome, and cancellation coverage continues to pass. Added checks -for a successful flag-bearing invocation followed by local help with an empty -value, explicit false and omitted values, distinct contexts/streams across -executions, handler-returned usage after successful registration, and help plus -usage against metadata registered after a session was prepared. The built-in -help handler and top-level dispatcher share target resolution/rendering. Source -review confirms `Execute` prepares one session from the cached neutral tree; -presentation reuses it when the tree pointer is unchanged and prepares against -new metadata only after successful registration. Parsing, input factories, -checks, and handlers are not rerun for presentation. Public signatures and the -Cobra facade boundary are unchanged. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `a852301` with this stage's -changes in the working tree. The five-sample command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformanceDispatch$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-dispatch-after-stage9.txt`; -focused wide and cold repeats are in -`/tmp/commandkit-performance-dispatch-stage9-repeat.txt` and -`/tmp/commandkit-performance-dispatch-stage9-cold-repeat.txt`. - -Compared with the Stage 1 baseline, small repeated success measured -38,671–44,179 ns/op, 29,576–29,578 B/op, and 269 allocations (baseline: -31,066–41,041 ns/op, 33,209–33,210 B/op, 287 allocations). The timing ranges -overlap; bytes fell by about 3.6 KB and allocations by 18. Local help measured -85,120–91,091 ns/op, 41,428–41,430 B/op, and 509 allocations (baseline: -103,022–116,183 ns/op, 78,176–78,177 B/op, 810 allocations). Explicit help -measured 89,431–116,591 ns/op, 41,917–41,918 B/op, and 516 allocations -(baseline: 101,998–111,895 ns/op, 78,152–78,153 B/op, 815 allocations). -Parser usage measured 28,521–46,876 ns/op, 30,128–30,129 B/op, and 292 -allocations (baseline: 62,596–74,475 ns/op, 66,363–66,364 B/op, 591 -allocations). Handler usage measured 29,563–53,319 ns/op, 29,976–29,977 -B/op, and 284 allocations (baseline: 61,878–72,264 ns/op, 66,211–66,212 -B/op, 583 allocations). - -The focused wide repeat measured success at 178,004–194,710 ns/op, 247,796– -247,806 B/op, and 1,758 allocations (baseline: 218,073–253,010 ns/op, -269,063–269,070 B/op, 1,898 allocations). Wide help measured 227,764–243,610 -ns/op, 259,685–259,689 B/op, and 1,998 allocations (baseline: 491,172– -622,188 ns/op, 549,923–549,940 B/op, 4,033 allocations). Deep success -measured 151,780–172,540 ns/op, 124,410–124,412 B/op, and 881 allocations -(baseline: 119,958–139,625 ns/op, 139,787–139,791 B/op, 1,074 allocations), -so this run was slower while reducing bytes and allocations. Deep help measured -253,765–324,263 ns/op, 157,797–157,808 B/op, and 1,238 allocations; its -focused Stage 1 baseline was 300,155–326,094 ns/op, 294,882–294,896 B/op, and -2,408 allocations. - -Cold small construction plus first execution measured 37,934–42,626 ns/op, -38,411–38,412 B/op, and 340 allocations (baseline: 38,152–50,235 ns/op, -38,275–38,276 B/op, 339 allocations). Cold wide measured 267,018–335,726 -ns/op, 305,212–305,220 B/op, and 2,196 allocations (baseline: 251,945– -315,276 ns/op, 291,822–291,827 B/op, 2,184 allocations). Both timing ranges -overlap their baselines; retained session coordination adds a small cold -allocation/byte cost. Results show lower help/usage work and lower repeated -allocation costs, with timing variation on repeated success and deep dispatch. - -## Stage 10: prepare configuration scope metadata once - -**Status:** complete. **Prerequisite:** Stage 9. - -**Files:** [config.go](../../config.go), [selectors.go](../../selectors.go), -configuration handler files, configuration/cancellation tests, scope benchmarks, -and evidence. Keep public `ConfigSuite`/`ConfigScope` unchanged. - -1. Introduce private `preparedConfigSuite[C]` with the normalized public suite, - ordered scope slice, `map[string]ConfigScope[C]` lookup, and discovery DTO. - Prepare it once in `RegisterConfig` after normalization. Use the existing - ordering comparator: `app`, `promptkit`, then other identifiers alphabetically. - Normalize/copy metadata before preparation so it remains instance-owned. -2. Replace the previous-selector loop in `normalizeConfigSuite` with seen-name - and seen-short maps, retaining validation order, scope-reference deduplication, - and the same collision categories. Preserve all existing naming rules. -3. Pass the private prepared suite into standard command constructors and - preflight/run helpers. Use its ordered slice for aggregate selection and - its map for named lookup, capability preflight, and acquisition. Update - validate/show/sources/explain together; no public integration signature changes. -4. Construct the discovery inventory from declared/installed operations during - registration and retain the private DTO. Encode text/YAML at invocation time. - This preparation must not call `NewContext`, acquisition, input checking, - native writers, or other runtime callbacks. -5. Keep selection validation in preflight and handlers, now using prepared - metadata. Keep selector applicability scans and fresh context projection. - Do not add mutable selected-scope memoization or public/internal input hooks - solely to avoid a second inexpensive validation pass. -6. Reuse discovery ordering/capability, selector projection/requiredness, unknown - scope, provider-error, and cancellation coverage. Ensure aggregate operations - check every selected capability before acquisition; discovery remains - metadata-only. Add only missing post-registration ownership/collision cases. -7. Compare scope execution and suite registration with Stage 2, including the - normal two-scope case. Record the retained slice/map/DTO cost and any timing - tradeoff; extra metadata is private to the registered suite. - -**Validation:** root configuration and cancellation tests plus scope/selector -benchmarks. Use `go test -mod=readonly -count=1 .` for root behavioral validation. -Preserve native reporting and per-operation output timing. - -**Completion:** scope sorting/discovery preparation occurs at registration, -scope lookup is indexed, and duplicate selector checks are linear in selector -count plus declared scope references. - -**Evidence:** `GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none -GOSUMDB=off go test -mod=readonly -count=1 .` passed, including existing -configuration, selector, discovery, and cancellation behavior. Added coverage -that caller mutations to scope and selector slices after registration do not -change discovery, capability selection, or projected inputs, and that duplicate -selector names and short names retain their error category. Registration now -normalizes owned metadata, prepares the ordered scopes, name index, installed -operation list, and discovery DTO once, then passes that private value through -validate/show/sources/explain and their preflight/run paths. Aggregate selection -checks every capability using the prepared metadata before any acquisition. -`NewContext`, acquisition, checks, native writers, and encoding are not called -while preparing the suite. Discovery renders the retained DTO at invocation -time. Scope sorting occurs once, named lookup uses the map, and duplicate -selector validation uses seen-name/seen-short maps while preserving validation -order and deduplicating scope references. Public `ConfigSuite` and `ConfigScope` -declarations and signatures are unchanged. - -Measurements used Go 1.26.8, linux/amd64, Linux 6.17.0-41-generic, Intel Core -i5-7260U CPU @ 2.20 GHz, based on source revision `a7960e5` with this stage's -changes in the working tree. The five-sample command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -run '^$' -bench '^BenchmarkPerformance(ConfigScopes|ConfigRegistration)$' -benchmem -benchtime=200ms -count=5 .`. -Raw output is in `/tmp/commandkit-performance-config-after-stage10.txt`; -focused repeats for selector-heavy registration and the ordinary two-scope -aggregate are in `/tmp/commandkit-performance-config-registration-repeat.txt` -and `/tmp/commandkit-performance-config-two-scope-repeat.txt`. - -Against Stage 2, two-scope discovery measured 16,788–21,062 ns/op, 18,557 -B/op, and 195 allocations (baseline: 23,840–30,007 ns/op, 21,161–21,162 -B/op, 223 allocations). Named selection measured 18,375–21,756 ns/op, -19,621 B/op, and 207 allocations (baseline: 24,841–26,340 ns/op, 21,817 -B/op, 228 allocations). Two-scope aggregate validation measured 22,977–28,152 -ns/op, 19,637–19,638 B/op, and 208 allocations in the focused repeat (baseline: -25,231–31,126 ns/op, 22,361–22,362 B/op, 237 allocations). - -At 32 scopes, discovery measured 18,253–20,311 ns/op, 21,070 B/op, and 199 -allocations (baseline: 31,439–37,167 ns/op, 28,141–28,142 B/op, 257 -allocations). Named selection measured 18,679–20,529 ns/op, 20,582 B/op, and -207 allocations (baseline: 29,123–74,374 ns/op, 22,775–22,778 B/op, 228 -allocations). Aggregate validation measured 25,036–33,981 ns/op, 22,702 B/op, -and 240 allocations (baseline: 45,548–63,471 ns/op, 29,781–29,782 B/op, 269 -allocations). - -Registration with 4 selectors measured 11,272–14,623 ns/op, 9,310 B/op, and -107 allocations (baseline: 12,573–14,789 ns/op, 8,911 B/op, 104 allocations). -With 64 selectors, the focused repeat measured 72,002–74,712 ns/op, 90,197– -90,200 B/op, and 494 allocations (baseline: 91,675–105,548 ns/op, -82,817–82,818 B/op, 485 allocations). The retained ordered slice, lookup map, -and discovery DTO add registration storage: about 399 bytes and 3 allocations -for 4 selectors, and 7.4 KiB and 9 allocations for 64 selectors. Selector-heavy -registration timing improved in the focused repeat; execution ranges improved -for discovery and named/aggregate selection. These benchmark timings vary and -are observations, not thresholds. - -## Stage 11: audit the completed target and reconcile documentation - -**Status:** complete. **Prerequisite:** Stages 1–10. - -**Files:** this plan, `performance.md`, -[internal overview](../internal/overview.md), developer/README navigation, -and stale references to the retired ReleaseKit plan. Focused corrections only -where the audit proves an incomplete target. - -1. Audit PF-01–06 against source and observed behavior: selected formatting, - indexed ancestry, prefix-only YAML analysis, full framed buffering, pending - registrations, immutable cache invalidation, invocation sessions across all - help/usage paths, and prepared configuration metadata. Identify authoritative - evidence for each target rather than infer completion from stage statuses. -2. Run the default suite once for the complete sprint: - - ```sh - GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -count=1 ./... - ``` - - Keep live services, the optional release publication exercise, and additional - race/platform/coverage gates unselected. Review production imports and exported - declarations using existing boundary checks and source evidence. -3. Rerun representative benchmarks with unchanged fixtures and comparable - environment. Summarize before/after data by PF ID, separate cold/repeated and - isolated/whole-command costs, and record remaining full-tree/full-buffer work. - Reuse a recent identical measurement when source and environment are unchanged. - Explain material regressions or collect more evidence before declaring success. -4. Update internal documentation to describe implemented cache/session ownership - and prepared metadata. Current CLI/GoDoc contracts should remain unchanged; - update them only for an actual clarification without inventing a new promise. -5. Update README and `docs/development.md` so current implementation navigation - points to this performance plan and roadmap. In `releasekit.md`, `initial.md`, - and `remediation.md`, remove or replace obsolete ReleaseKit-plan references - with the owning completed roadmap/runbook as appropriate. Remove its obsolete - final-stage fragment references. Do not preserve the retired stage assignments - or restart completed release work. -6. Check affected document links/fragments, prose status, and whitespace. Mark - the roadmap implemented only when every selected target has evidence. Record - the stage commits, measurement revisions, check results, and any qualifications - here, then commit the audit and leave a clean workspace. - -**Validation:** the default suite, comparative measurements, facade/import -review, and affected documentation/link checks described above. Reuse unchanged -stage evidence where it directly proves the final target. - -**Completion:** all six target improvements and both selected approaches are -implemented with relevant behavioral and efficiency evidence; maintained docs -identify their current owners. No performance guarantee or additional release -gate has been introduced. - -**Evidence:** Audited PF-01–PF-06 against the current implementation and -behavioral coverage. PF-01 selects the PromptKit renderer before serialization; -PF-02 indexes backend commands to declarations and uses parent links for the -selected path; PF-03 caches immutable bridge metadata per `App` and uses one -mutable adapter session per `Execute`, including help and usage; PF-04 scans -only YAML framing lines but retains complete framed bytes; PF-05 validates and -clones pending registrations before atomically installing them; PF-06 prepares -owned ordered scope metadata, lookup, and discovery data at registration. The -existing focused tests cover refresh after registration, parser/help/usage -session reuse, YAML boundaries/directives, registration rollback, prepared -scope ownership, selector collisions, and callback timing. OD-1 and OD-2 remain -as selected: backend state is fresh per invocation, and YAML output retains a -full framed buffer. - -The default sprint suite passed on source revision `62b4a48` with -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test --mod=readonly -count=1 ./...`. Packages `commandkit`, `internal/cobra`, and -`scripts` passed; both examples compiled. `go list` and `go doc -all .` confirmed -that Cobra/pflag remain confined to `internal/cobra`, the adapter does not -import the root package, and the root exported declarations retain their -existing signatures. Review of the sprint Go diff found no changed or added -root exported declarations. - -Final representative measurements used Go 1.26.8, linux/amd64, Linux -6.17.0-41-generic, Intel Core i5-7260U CPU @ 2.20 GHz, source revision -`62b4a48`, and the unchanged fixtures from earlier stages. The five-sample -command passed: -`GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test --mod=readonly -run '^$' -bench '^BenchmarkPerformance' -benchmem --benchtime=200ms -count=5 . ./internal/cobra`. Raw output is in -`/tmp/commandkit-performance-final.txt`. Dispatch, prepared-scope, and scope -registration benchmarks were then repeated with the same five-sample settings. -Shortly after the measurements, the host load average was 3.62 on four logical -CPUs; historical stage measurements did not record load. Cross-run timing -comparisons are therefore inconclusive, while bytes and allocation counts -remained stable. - -- **PF-01:** For 128 prompt inputs, final text measured 159,091–172,388 ns/op, - 126,782–126,787 B/op, and 1,143 allocations; YAML measured 1,240,053–1,534,668 - ns/op, 1,262,298–1,262,330 B/op, and 5,079 allocations. Stage 2 recorded - 145,524–145,531 B and 1,171 allocations for text and 1,393,508–1,393,568 B - and 6,039–6,040 allocations for YAML. Four-input YAML is now 69,677–69,678 B - and 480 allocations versus 74,730–74,733 B and 557 at baseline. Selected - rendering reduces report work and allocations; profile-text timings remain - noisy. -- **PF-02:** Final adapter Parse measured 242,960–242,969 B/op and 1,706 - allocations for the shallow/wide fixture, and 119,560 B/op and 827 - allocations for the deep fixture. Stage 4's isolated change reduced deep - Parse by 384 B and one allocation; later session work adds a small wrapper - cost. Tree construction remains in these Parse measurements; selected-path - lookup is recorded separately in Stage 4. -- **PF-03:** Final repeated success measured 53,796–61,372 ns/op, - 29,580–29,581 B/op, and 269 allocations. Local and explicit help used - 41.4–41.9 KB and 509/516 allocations; parser and handler usage used about - 30 KB and 292/284 allocations. Stage 9 measured 38,671–44,179 ns/op for - repeated success and about 41.4–41.9 KB with the same help allocation counts. - A focused repeat remained slower in time while allocation results stayed - stable. The host load noted above and the absence of a prior load record - prevent attributing this timing difference to the source change. Cold - construction plus first execution measured 84,000–93,954 ns/op and - 38,418–38,419 B for a small app, and 616,203–678,200 ns/op and about 305 KB - for a wide app. The cached neutral tree still requires construction once per - metadata generation, and mutable backend trees are still built per invocation. -- **PF-04:** Direct 4 KiB framing measured 1,193–1,256 ns/op, 4,864 B/op, and - one allocation; direct 1 MiB framing measured 188,617–561,502 ns/op, - 1,056,768–1,056,770 B/op, and one allocation. The 1 MiB aggregate writer - measured 1,624,170–1,806,960 ns/op, about 4.245 MB, and 185 allocations, - versus the Stage 2 baseline of about 8.695 MB and 215–216 allocations. The - full framed copy remains part of the selected OD-2 behavior. -- **PF-05:** Final 128-entry individual registration measured 101,116–118,013 - ns/op, 29,420–29,421 B/op, and 293 allocations, compared with the Stage 1 - baseline of 414,618–492,261 ns/op, about 405 KB, and 784 allocations. A - 128-entry batch measured 104,559–118,844 ns/op, about 35,992 B/op, and 296 - allocations, retaining the documented extra pending-index and map-growth - cost compared with the smaller Stage 1 batch allocation. The focused run - confirms this remains an allocation/timing tradeoff, not a correctness issue. -- **PF-06:** Final two-scope discovery, named selection, and aggregate - validation measured 33,003–34,199, 38,275–45,600, and 44,677–65,937 ns/op, - respectively; allocation counts were 195, 207, and 208. At 32 scopes, - discovery used 199 allocations, named selection 207, and aggregate validation - 240. The focused repeat also remained slower than Stage 10 measurements while - retaining the same allocation counts. Compared with Stage 2, - retained metadata reduces two-scope discovery from 21,161 B/223 allocations - to 18,559–18,560 B/195, and 32-scope aggregate validation from 29,781–29,782 - B/269 to 22,705–22,706 B/240. The prepared suite retains ordered scopes, - lookup, and discovery data; registration cost grows accordingly. - -The runbook remains the owner of release operations, the ReleaseKit roadmap -owns adoption status, and this performance roadmap and record own PF-01–PF-06. -Updated the internal overview, README, and contributor navigation; replaced -obsolete ReleaseKit-plan links in the releasekit, initial, and remediation -records with the completed historical adoption record or current owner. Local -Markdown links and fragments passed checks across all eight affected documents, -and `git diff --check` passed. The Stage 1–10 implementation commits are -`aed4c59`, `a431540`, `628dc78`, `ae656d8`, `3f8841f`, `5816dd3`, `3ad3559`, -`a852301`, `a7960e5`, and `62b4a48`; the final audit is recorded in this commit. - -Remaining costs are full backend tree construction for each invocation and a -full framed YAML buffer for delivery. No public performance guarantee or new -release gate was added. diff --git a/docs/roadmap/initial-plan.md b/docs/roadmap/initial-plan.md deleted file mode 100644 index a6a2eac..0000000 --- a/docs/roadmap/initial-plan.md +++ /dev/null @@ -1,202 +0,0 @@ -# Preparing the initial CommandKit feature roadmap - -Status: roadmap preparation and implementation-plan handoff complete. - -Date: 2026-10-07. - -The [feature roadmap](initial.md) records the selected initial target and its -completion. The [completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md) -was prepared from that review and has been executed. Checked entries below -record the completed preparation process; they are not assignments to restart -planning. - -## Historical preparation process - -The checklist below was used to select the initial feature target and prepare an -ordered Luna implementation plan. Its instructions and suggested outline are -retained as planning history. Current public contracts belong in Go declarations -and GoDoc, operator behavior in the [CLI reference](../cli.md), and usage guidance -in the [consumer guide](../consumers/guide.md). - -The [architecture policy](../policy/architecture.md) and accepted ADRs control -architectural choices. This document owns the preparation process; `initial.md` -owns the initial feature targets. Exact implemented contracts belong in -Go declarations, GoDoc, and the CLI reference under the -[documentation policy](../policy/documentation.md). - -## 1. Establish authoritative requirements - -- [x] Review all nine accepted ADRs and the architecture policy. -- [x] Build a requirements checklist linking each requirement to its authority. -- [x] Review the four numbered roadmaps as evidence and design proposals: - [CLI plan](01-cli-plan.md), [dispatcher](02-dispatch.md), - [backend](03-backend.md), and [facade](04-facade.md). -- [x] Identify conflicts with accepted decisions and carry the controlling choice - into the new roadmap. -- [x] Distinguish accepted requirements, remaining design choices, and proposed - delivery scope. Approval of this drafting process leaves those design choices - to be resolved during roadmap preparation. - -Use these ADR owners for traceability: - -| Topic | Authority | -| --- | --- | -| Dispatch, registration, typed inputs, and consumer boundaries | [ADR 0001](../adr/0001-command-dispatch-and-inputs.md) | -| Initial backend and invocation state | [ADR 0002](../adr/0002-cobra-backend.md) | -| Public facade and internal adapter | [ADR 0003](../adr/0003-public-facade.md) | -| Standard operations and capability-based availability | [ADR 0004](../adr/0004-standard-inspection-surface.md) | -| Outcomes, streams, and diagnostic delivery | [ADR 0005](../adr/0005-invocation-outcomes.md) | -| Grammar and vocabulary guidance | [ADR 0006](../adr/0006-command-grammar.md) | -| Native YAML and combined display | [ADR 0007](../adr/0007-native-yaml-reports.md) | -| Semantic comparison and sensitivity gaps | [ADR 0008](../adr/0008-semantic-configuration-diff.md) | -| Scopes, supported operations, and selection defaults | [ADR 0009](../adr/0009-configuration-scopes.md) | - -Confirm these known differences from older planning material: - -- Singleton flags use the last occurrence; repeatable flags accumulate in order. -- Configuration operations, including validation, default to `app`. -- Straightforward implementation may live in the root package. -- Providers can expose subsets of inspection capabilities. -- Loading all selected views before output is specifically a `config show` - requirement; other operations define their own output timing. - -**Result:** a traceable requirements checklist and a reconciliation of older -planning assumptions. - -## 2. Select a concrete package layout - -Evaluate this starting recommendation: - -| Package | Target responsibilities | -| --- | --- | -| Root `commandkit` | Public API; instance registry; command groups; typed bindings and presence; invocation coordination; outcomes; standard handlers; scope metadata; ConfigKit/PromptKit integration contracts; report composition. Straightforward unexported implementation can live here. | -| `internal/cobra` | Translate backend-neutral declarations into Cobra/pflag machinery; implement parsing and help mechanics; maintain independent invocation state; translate backend-owned failures. | - -- [x] Define each package's purpose, owned features, inputs, outputs, dependencies, - and extension points. -- [x] Describe the boundary between the root and adapter, including how declarations - and callbacks cross it while retaining supported value and error semantics. -- [x] Keep Cobra/pflag types and operations confined to the internal adapter and - retain root-owned public named types. -- [x] Evaluate whether comparison or inspection code warrants another cohesive - internal package, using concrete implementation and integration needs. -- [x] Settle package placement during roadmap preparation so the later plan gives - Luna a defined target layout. -- [x] Keep package structure proportionate to the actual responsibilities under - the architecture and agent policies. - -**Result:** a target package inventory and dependency/ownership map. - -## 3. Define the initial feature inventory - -Organize the inventory around these feature groups: - -| Group | Features to evaluate | -| --- | --- | -| Command infrastructure | Construction, registration, groups, ownership checks, typed inputs, presence, repetition, operands, help, and invocation. | -| Identity and outcomes | Application/component version reporting, classifications, supported error identity, streams, and delivery failures. | -| Configuration inspection | Scopes, validation, native display, combined display, sources, explanation, and semantic comparison. | -| PromptKit inspection | Configuration scope, prompt/profile catalogs, and definition inspection. | -| Consumer integration | Lazy acquisition, selector applicability, upstream public types, and application-owned callbacks. | - -- [x] Assign stable feature identifiers for later implementation-plan traceability. -- [x] For each feature, specify its observable result, package owner, provider - requirements, dependencies, and completion evidence. -- [x] Describe CommandKit behavior and provider result contracts separately from - recommended consumer practices. -- [x] Build an upstream capability matrix from current supported ConfigKit and - PromptKit public APIs, recording the inspected revisions or versions. -- [x] Identify which capabilities are available now and which need upstream work. -- [x] For each missing capability, recommend including the upstream work or - explicitly deferring that feature, with the reason and affected targets. -- [x] Settle initial delivery scope before preparing the ordered implementation - plan. Missing capabilities leave independently supported operations available. - -**Result:** feature specifications and an explicit initial delivery scope with its -upstream dependencies and deferrals. - -## 4. Evaluate existing code for reuse - -Begin with these review candidates: - -- [Notarius configuration commands](../../../notarius/internal/cli/configkit_commands.go): - native effective configuration and explanation integration. -- [Scriptorium inspection commands](../../../scriptorium/internal/adapter/cli/inspect.go): - PromptKit inspection acquisition and report preparation. - -Expand to other consumers where their implementations provide useful evidence. -Use the repository's code-discovery workflow when locating and tracing code. - -- [x] Identify reusable logic and the behavior it supplies. -- [x] Separate it from application-specific acquisition, schemas, domain resolution, - parsers, names, statuses, and formats. -- [x] Evaluate the candidate against the accepted CommandKit contracts and the - selected feature target. -- [x] For each proposed port, record the source revision, relevant symbols/files, - adaptation work, and dependencies. -- [x] Verify applicable licensing and attribution treatment under the - [OSS policy](../policy/oss.md) before copying material. -- [x] Identify reusable examples or fixtures that demonstrate meaningful behavior. -- [x] Use representative simple and complex consumer examples to evaluate whether - the proposed API removes repeated infrastructure and remains practical to wire. - -Sibling checkout links are review references. CommandKit implementation and -consumer examples use supported published APIs and module dependencies. - -**Result:** a reuse assessment and representative integration examples, with -provenance and adaptation requirements for proposed ports. - -## 5. Resolve implementation choices explicitly - -- [x] Recommend construction, registration, command-group, and typed-binding API - shapes, including presence-aware inputs. -- [x] Select narrow provider representations against concrete integration needs, - reusing upstream public types where useful. -- [x] Define acquisition lifetime and any justified dependency coordination or - result reuse, with callback ownership clear. -- [x] Specify configuration and context selectors and their applicability. -- [x] Define diagnostic presentation responsibility and delivery-failure handling. -- [x] Select report formats, framing, and schemas for the included operations. -- [x] Define comparison selection inputs for included diff capabilities. -- [x] Select the module baseline and supported dependency versions using the - applicable policies and current dependency requirements. -- [x] For viable alternatives, record a recommendation and a short analysis of - each alternative. -- [x] Resolve choices that would otherwise require Luna to invent public behavior - or package boundaries while following the implementation plan. - -API shapes in planning remain design targets until implemented. Go declarations -and GoDoc will own the exact exported contracts. Significant changes to accepted -architecture follow the ADR process in the documentation policy. - -**Result:** a coherent design with remaining decisions explicitly tracked and -resolved to the depth needed by the later implementation plan. - -## 6. Define completion and prepare the handoff - -- [x] Define observable completion criteria for each included feature. -- [x] Cover supported commands, capability discovery, native YAML preservation, - outcomes, backend isolation, and representative public API usage. -- [x] Identify proportionate evidence under the [testing policy](../policy/testing.md), - prioritizing real adapter behavior and the supported public consumer boundary. -- [x] Identify documentation and attribution deliverables as their corresponding - implementation lands. -- [x] Review the complete draft against its requirements checklist and package map. -- [x] Make upstream work, deferrals, and unresolved decisions visible in the draft. -- [x] Review the targeted end state before translating it into implementation tasks. -- [x] Prepare the subsequent staged plan with ordered tasks, prerequisites, precise - deliverables, and completion checks mapped to the roadmap's feature identifiers. - -**Result:** a reviewed feature roadmap and the completed staged implementation -plan suitable for Luna. - -## Historical outline for `initial.md` - -1. Authority and initial scope. -2. Target package layout and dependencies. -3. Public API and integration model. -4. Feature specifications by package. -5. Ownership boundaries. -6. Upstream dependencies and reuse candidates. -7. Explicit deferrals. -8. Completion criteria. diff --git a/docs/roadmap/initial.md b/docs/roadmap/initial.md deleted file mode 100644 index 9708d1a..0000000 --- a/docs/roadmap/initial.md +++ /dev/null @@ -1,627 +0,0 @@ -# Initial CommandKit feature roadmap - -Status: selected initial target implemented; completed design baseline. - -Date: 2026-10-07. - -## Purpose and authority - -This document defines the selected initial target for the library: packages, -features, integration contracts, dependencies, and completion evidence. It was -prepared using [the agreed checklist](initial-plan.md). Implementation steps and -stage evidence belong in the [completed initial implementation record](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/3871d837489b9955998b362587a52b47282dc021/docs/roadmap/implementation.md). -Detailed specifications below preserve the selected design baseline; they are -planning history, not a parallel current API or operator reference. The included -target is implemented; the table below records feature status. - -| Included feature IDs | Status | Evidence | -| --- | --- | --- | -| API-01, REG-01, INPUT-01, BACK-01, INV-01, OUT-01 | complete | Root API and dispatcher tests; `go test ./...`. | -| HELP-01, VER-01 | complete | Help/version behavior tests; `go test ./...`. | -| INT-01, CFG-01–05 | complete | Configuration scope, validation, show, sources, and explain tests; `go test ./...`. | -| PK-01 | complete | PromptKit scope adapter tests; `go test ./...`. | -| PK-02, PK-03 | complete | Prompt/profile inspection tests; `go test ./...`. | -| DIFF-01, CAT-01 | deferred | Require upstream safe snapshot and catalog APIs; see [deferred capability targets](#deferred-capability-targets). | - -The [architecture policy](../policy/architecture.md) and nine accepted ADRs control -this roadmap. The delivery scope, typed API model, selector/report behavior, and -full profile inspection described here were selected during roadmap review. -These implementation choices operate within the accepted architecture. Exact -exported contracts belong in Go declarations and GoDoc, navigated through the -[consumer guide](../consumers/guide.md); implemented operator contracts belong in -the [CLI reference](../cli.md). The [internal overview](../internal/overview.md) -owns current package inventory and mechanics. - -### Requirements and traceability - -| Requirement | Authority | Feature targets | -| --- | --- | --- | -| Own dispatch; use explicit instance registries, composable groups, typed inputs, and capability-based standard families. Keep application domain behavior with applications. | [ADR 0001](../adr/0001-command-dispatch-and-inputs.md) | REG-01, INPUT-01, INV-01, INT-01 | -| Use Cobra/pflag internally; initially rebuild backend state for each invocation. | [ADR 0002](../adr/0002-cobra-backend.md) | BACK-01, INPUT-01 | -| Expose one root facade with root-owned public named types and no backend leakage. | [ADR 0003](../adr/0003-public-facade.md) | API-01, BACK-01 | -| Supply standard help/version and available configuration/PromptKit inspection operations; families may support different subsets. | [ADR 0004](../adr/0004-standard-inspection-surface.md) | HELP-01, VER-01, CFG-01–05, PK-01–03; deferred DIFF-01, CAT-01 | -| Return explicit classifications and recommended statuses; preserve supported cause identity and report delivery failures. | [ADR 0005](../adr/0005-invocation-outcomes.md) | OUT-01 | -| Apply namespace/resource-first grammar, options after the complete command path, interspersed operands, presence, and selected repetition rules. | [ADR 0006](../adr/0006-command-grammar.md) | INPUT-01, HELP-01 | -| Preserve native effective YAML; prepare all selected show views before writing; frame aggregate display as separate documents. | [ADR 0007](../adr/0007-native-yaml-reports.md) | CFG-03 | -| Compare safe semantic snapshots with sensitivity union and explicit coverage gaps when comparison is enabled. | [ADR 0008](../adr/0008-semantic-configuration-diff.md) | deferred DIFF-01 | -| Declare scope capabilities; default to `app`; preserve the meaning and coverage of `all`; order scopes consistently. | [ADR 0009](../adr/0009-configuration-scopes.md) | CFG-01–05, INT-01 | - -The [CLI planning record](01-cli-plan.md), [dispatcher record](02-dispatch.md), -[backend record](03-backend.md), and [facade record](04-facade.md) preserve the -review history. These corrections were selected for the initial target: - -- Singleton flags use the last supplied occurrence, including mixed `--name value` - and `--name=value` spellings. Repeatable flags accumulate in order. -- Every configuration operation, including `validate`, defaults to `app`. -- Straightforward private implementation may live in the root package. A - forwarding-only facade and a separate internal engine are unnecessary targets. -- Partial capabilities remain useful; neither scopes nor families need every verb. -- Preparing every selected view before report output is a `config show` - requirement. Other operations have their own output timing. -- The older acquisition graph and shared-load mandates were superseded by - application-composed callbacks. Exact declarations, selector behavior, and - report layouts are owned by GoDoc and the CLI reference. Old illustrations - remain historical evidence. - -## Initial delivery scope - -Deliver the dispatcher, public registration/binding API, identity/outcomes, and -inspection operations supported by ConfigKit v0.5.0 and PromptKit v0.12.0. -Applications can use CommandKit without registering either integration; the Go -module still declares the dependencies used by its bundled helpers. - -| Family | Initial target | -| --- | --- | -| Identity and discovery | `help`, command/group help, `version`, explicit CommandKit version selection | -| Configuration | `config scopes`, `validate`, `show`, `sources`, `explain`, including explicit aggregate validation/display | -| PromptKit configuration | The `promptkit` configuration scope, independently of definition inspection | -| PromptKit definitions | `promptkit show prompt` and `promptkit show profile`, including effective `ExtraParams` | -| Application commands | Typed custom leaf commands, nested groups, and groups with their own runnable handler | - -Catalog listing and semantic comparison remain deferred until the owning -libraries expose the required public contracts. Their absence appears accurately -in help and capabilities. The implemented target uses the released inspection -APIs; upstream snapshot/catalog enhancements are separate follow-up work. - -This scope provides meaningful configuration inspection immediately and avoids -requiring an initial consumer migration to wait for every future capability. - -## Target packages and dependencies - -Create two production packages. Keep comparison and inspection helpers as private -root implementation when needed; the current target does not justify another -production package or a public integration subpackage. - -| Package | Purpose and owned features | Inputs and outputs | Dependencies and extension points | -| --- | --- | --- | --- | -| Root `commandkit` | Sole public facade; registry, typed bindings, standard handlers, provider integration, reports, identity, and outcomes | Accepts metadata, typed command declarations, acquisition callbacks, context, arguments, and caller streams; returns registration errors and invocation outcomes | Standard library, public ConfigKit/PromptKit APIs, YAML encoder, and the internal adapter. Consumers extend through commands, groups, parsers, scopes, and supported provider callbacks. | -| `internal/cobra` | Routing/parsing/help adapter; fresh backend state; conversion of backend-owned failures | Accepts neutral command/flag/operand metadata, binding callbacks, and invocation callbacks; returns neutral parse/help results and classified syntax failures | Cobra/pflag and standard library. Its bridge is internal and carries no Cobra/pflag objects back to the root. | - -Dependency direction is root → adapter → Cobra/pflag. The adapter does not import -the root. Root command declarations are lowered into the adapter's small neutral -bridge; closures bind freshly allocated typed inputs and invoke root/application -handlers. The root translates bridge failures into its public outcomes. Reuse -standard `context.Context`, `io.Writer`, and ordinary Go values at this boundary. - -Keep registry policy, capability checks, standard handlers, and reports in the -root. Cobra supplies routing and parsing machinery; its defaults must be adapted -where they differ from the accepted grammar. Do not copy its entire API into -CommandKit or introduce a selectable backend abstraction. - -### Module baseline - -Use the following reproducible starting baseline: - -| Item | Initial baseline | Reason | -| --- | --- | --- | -| Module | `gitea.maximumdirect.net/eric/CommandKit` | Matches project identity and the existing library suite's module convention. | -| Go | `1.25.5` | Matches PromptKit v0.12.0's declared minimum; ConfigKit v0.5.0 declares 1.25.0. | -| ConfigKit | `v0.5.0` | Reviewed released inspection API. | -| PromptKit | `v0.12.0` | Reviewed released configuration and named-definition inspection API. | -| Cobra | `v1.10.1` | Concrete initial pin implementing the accepted backend decision. Its [module declaration](https://github.com/spf13/cobra/blob/v1.10.1/go.mod) requires pflag v1.0.9. | -| pflag | `v1.0.9` | Match that Cobra baseline; its [module declaration](https://github.com/spf13/pflag/blob/v1.0.9/go.mod) fits the selected Go baseline. | -| YAML encoder | `go.yaml.in/yaml/v4 v4.0.0-rc.6` | Match ConfigKit's existing dependency for CommandKit-owned YAML reports. Native configuration writers remain authoritative. | - -These pins identify the initial baseline without claiming they are the newest -releases. Resolve and review the actual module graph and license notices when -adding dependencies. -Deferred snapshot/catalog capabilities will require released upstream versions -containing the new public APIs and a revised capability assessment. - -## Public API and integration model - -### API-01: public facade - -**Owner:** root. **Prerequisites:** registry and invocation contracts below. - -Expose an application handle with private state and a small deliberate method -set. Use construction from application identity and explicit initial command -registrations, registration methods for groups/standard suites, and invocation -with context, arguments, and caller streams. Keep runtime dependencies in handler -closures or a separate typed execution dependency parameter; they are not parsed -CLI fields. -Construction automatically installs help and version from identity/build metadata. -Provider registration assembles the other standard families' supported operations. - -The target concepts are identity, application/registry handle, command/group -declarations, typed bindings, presence, invocation environment, outcome, and scope -registration. Public named CommandKit types live in the root. Public ConfigKit -and PromptKit types are deliberate integration dependencies where useful. -Use generic package functions/factories with explicit typed binding setters and -composable groups. Go methods cannot declare their own type parameters, so generic -entry points belong in package functions/factories. Typed declarations and captured -views retain their selected ownership and supported public value/error semantics. - -**Completion evidence:** an external consumer uses only the root facade to -register and execute commands; public signatures, callbacks, fields, constraints, -and method sets contain no backend/internal types. No public aliases, anonymous -embedding, loosely typed bridge values, or returned backend errors defeat this -boundary. Caller-supplied values/errors retain their documented treatment. - -### REG-01: instance registry and command groups - -**Owner:** root. **Provider requirements:** none. **Depends on:** API-01. - -Use one metadata declaration for each command's path, description, operands, -flags, bindings, and handler. Compose groups explicitly per application instance. -Support nested custom commands and a group that has both children and a runnable -handler. Groups without handlers show help when invoked bare. - -Reject duplicate command paths and replacement of standard handlers. Own the -`config` namespace when installed and `promptkit` when installed: applications -cannot insert private children underneath them. Additional application families -remain registerable without needing the standard families' verb subsets. - -Build standard command availability from declared capabilities. Validate missing -wiring at registration; never load files to discover operations. Return errors -from registration rather than allowing registration order to choose a winner. - -**Completion evidence:** two separate instances have independent registries; -collisions and reserved-family violations return clear errors; nested custom -groups work; partial standard suites expose only their available operations. - -### INPUT-01 and BACK-01: typed inputs and adapter behavior - -**Owners:** root for bindings/presence; adapter for backend mechanics. -**Provider requirements:** none. **Depends on:** REG-01. - -Use generic command factories with explicit typed flag/operand setters and -a typed handler. Allocate the input struct for each invocation. A presence wrapper -such as `Supplied[T]` carries a value and whether it was supplied; omission differs -from an explicitly supplied empty string, false, or zero. A repeatable binding -collects ordered values. Support ordinary scalar conversions and caller-provided -typed domain parsers without handler lookups by flag name. - -Metadata expresses required operands/flags, counts, and declared incompatible -combinations. Parsing and declared input-shape failures are usage outcomes; -application domain validation stays with the application handler. Do not infer -additional incompatibilities from parser convenience. - -Apply ADR 0006's grammar through the adapter: standard long lowercase hyphenated -flags, separated/equal string values, boolean presence or explicit boolean value, -`--` termination, options after the full command path, and interspersed options -and operands within that command. Help bypasses missing execution requirements; -unknown help paths/flags still fail as usage errors. - -Initially rebuild the Cobra tree and binding state for each invocation. Repeated -calls retain no prior values, slices, or presence bits. Caller closures keep their -own lifecycle; this design does not establish concurrent dispatch support. - -**Completion evidence:** public invocations exercise the real adapter, explicit -zero/false/empty values, omission, singleton last-wins, ordered repetition, -interspersed operands, termination, and repeated executions with fresh inputs. -Help routing must follow CommandKit's grammar even where Cobra differs. - -### INV-01 and OUT-01: invocation, outcomes, and diagnostics - -**Owner:** root, with syntax adaptation in the adapter. -**Provider requirements:** handlers/acquisition callbacks. **Depends on:** INPUT-01. - -Pass caller context to handlers and acquisition callbacks. CommandKit does not -create the executable entry point, install signal handlers, or call `os.Exit`. -Return explicit success, usage, operational, or application-domain classification, -recommended status, and supported cause identity. Standard statuses are 0, 2, and -1 respectively for success, usage, and operational failure. Preserve an -application handler's explicit domain classification and suggested status. - -Make root invocation the single presenter of CommandKit diagnostics. -Standard handlers return report/delivery information and safe diagnostic data; -the adapter suppresses its own automatic error printing. Use public -`configkit.WriteDiagnostics` for ConfigKit diagnostics and neutral presentation -for syntax errors. Pair diagnostics with supplied source records where useful. -Do not print an owning-library diagnostic twice through nested CommandKit paths. - -Return one root-owned outcome containing classification, suggested status, -operation cause, delivery failure, and a clear diagnostic-delivery indication. -This indication distinguishes a diagnostic already presented from one whose write -failed. Preserve both the operation cause and a delivery error when both occur; -do not replace either with a backend error. Invocation returns this outcome -without a separate error result. Warnings alone allow success. Report or diagnostic -writer errors are operational failures and can leave partial output. - -Callbacks control their own output. Consumer guidance should recommend returning -diagnostics to the standard path and avoiding repeated presentation, without -prescribing all downstream error handling. Upstream APIs determine how much -underlying error identity survives; CommandKit cannot recover causes an upstream -library deliberately withholds. - -**Completion evidence:** usage guidance appears on the diagnostic stream; -reports appear on the report stream; warnings permit success; callback, -cancellation, report-write, and diagnostic-write failures are classified correctly; -public causes remain usable with `errors.Is`/`errors.As` where supported. - -### INT-01: acquisition and provider contracts - -**Owner:** root. **Depends on:** registry, typed inputs, outcomes. - -Use a typed configuration-suite factory parameterized by an -application-owned inspection-context input. It installs the standard input -bindings once, plus explicit typed application selector bindings, and scope -registrations with acquisition callbacks. A simple consumer uses an empty context -type. A complex consumer supplies campaign or other domain selection as typed -fields. Generic suite helpers and small capabilities provide this assembly without -a universal untyped service container or handler access to parser objects. - -Each scope declares supported operations and obtains a captured view only on an -invocation that needs it. Use small operation-specific interfaces/callbacks: -native effective writer; source reader; safe explanation reader/writer; and -validation callback. Reuse `configkit.SourceInfo`, `Diagnostic`, `Path`, and -`Explanation` rather than creating parallel provenance types. A bundled generic -ConfigKit helper connects a loader returning `*configkit.Result[T]`; a PromptKit -helper connects engine acquisition and `ConfigurationInspection`. Missing an -operation must not require dummy implementations of other interfaces. - -For a selected operation, acquire its scope once and retain that view through -reporting. A bundled helper can reuse the same loaded result for diagnostics and -the report. Aggregate show retains all selected views before writing. Other -operations need no application-wide cache or dependency graph. - -When an engine depends on application configuration, the application acquisition -callback composes that dependency. It may share results in an invocation-local -closure. Document that pattern, without requiring one universal loading method, -forbidding consumer effects, or promising that arbitrary callbacks never reload. -Recommend sharing inspection and execution loading/resolution where practical. - -**Completion evidence:** metadata-only commands do not invoke acquisition; -single-scope operations acquire only their target; aggregate show observes its -preparation rule; simple and complex consumer examples require no parallel -dispatcher, manual standard-command parser, or duplicated standard report logic. - -## Standard command features - -All features below belong to the root; routing, flag conversion, and help -mechanics use the adapter. Their common prerequisites are REG-01, INPUT-01, -INV-01, and OUT-01. Provider requirements and additional dependencies are stated -per feature. The following flags/report shapes are selected implementation -targets for the initial standard suite. - -### HELP-01 and VER-01: help and identity - -- Help describes installed standard and custom commands using registry metadata. - Root bare invocation, `help [COMMAND…]`, `--help`, and `-h` follow ADR 0006. -- Use `version` and `version --scope commandkit`; default output is only - application identity. Version subjects are separate from configuration scopes. -- Application identity is supplied at construction. Recommend obtaining embedded - CommandKit identity from Go build information, respecting module replacement - metadata; use an explicit development/unknown label when a tag is unavailable. - Do not invent a separate integer CLI version. Use a text default and - optional `--format yaml` for version records. - -**Provider requirements:** identity metadata only. **Completion evidence:** help, -version, and discovery work with missing/invalid configuration and never invoke -acquisition callbacks. Default version excludes dependency inventory; explicit -CommandKit selection identifies the embedded component accurately. - -### CFG-01: scope metadata and selection - -`config scopes` lists identifiers and supported operations in order: `app`, -`promptkit`, then additional identifiers alphabetically. Use text by default -and `--format yaml` producing `scopes: [{name, operations}]`. - -All installed configuration operations use `--scope NAME`, defaulting to `app`. -`validate` and `show` additionally accept `all`. Check requested coverage before -acquisition. An unsupported scope/operation is usage failure with available -choices; `all` never silently skips a scope. If `app` is absent, its default -selection fails with useful choices rather than silently selecting another scope. - -**Provider requirements:** registration metadata only. **Completion evidence:** -discovery matches installed handlers and partial capabilities; aggregate coverage -errors occur before any acquisition; ordering and defaults match ADR 0009. - -### CFG-02: validation - -`config validate` invokes the selected provider's configuration load/validation -boundary. ConfigKit's bundled helper regards successful load and required owning -validation as success. PromptKit's helper constructs/obtains a valid engine; -it does not run a prompt or probe model availability. Application domain context -validation, when needed for its inspection view, belongs in its callback. - -Use text by default and `--format yaml` with a `scopes` sequence of completed -validation records (`name`, `valid`). For `all`, preflight capability coverage, -then validate in scope order and report successful scopes as they complete; -stop on the first operational failure. Diagnostics explain the failure and the -outcome indicates incomplete completion. This selected validation timing preserves -show's separate preparation rule. - -**Provider requirements:** validation/acquisition callback and safe diagnostics. -**Depends on:** INT-01, CFG-01. **Completion evidence:** default validates `app`; -explicit `all` validates requested coverage; invalid configuration yields status 1; -warnings alone do not fail; no model execution is triggered by bundled handlers. - -### CFG-03: native effective display - -`config show` writes the selected scope's owning-library effective YAML. It must -not marshal `Result.Config`, reinterpret defaults, remove nulls, or rebuild the -native document from runtime structs. Use YAML as its sole initial format; -accept `--format yaml` for explicitness. - -For `--scope all`, acquire and complete required owning validation of every view -before writing any report bytes. Compose separate native documents in scope order, -with YAML separators and scope-label comments. Use `---` followed by -`# scope: NAME` before each document. Single-scope show writes native output -without an added scope envelope. Preserve native content; framing must account -for any native document marker without creating accidental empty documents. - -**Provider requirements:** native writer plus successful acquisition/validation. -**Depends on:** INT-01, CFG-01. **Completion evidence:** single native output is -preserved; aggregate YAML has one labeled document per selected scope in order; -a later acquisition failure leaves no successful prefix; writer failure returns -operational failure and may leave partial output. - -### CFG-04: source inventory - -`config sources` exposes the selected captured view's public source records. -Retain the owning source IDs, labels, paths, kinds, layers, underlay indices, and -import locations where available; missing fields do not acquire invented values. -Keep owning-library record order. Use readable text by default and -`--format yaml` with `{scope, sources}` and explicit snake-case source fields. - -**Provider requirements:** public source reader and acquisition. -**Depends on:** INT-01, CFG-01. **Completion evidence:** acquired and synthetic -records remain identifiable; import references correlate with owning IDs; -reporting does not reload files or confuse provenance with effective values. - -### CFG-05: path explanation - -Use `config explain --path POINTER`, including an explicitly supplied empty -pointer for the root. Use public `configkit.ParsePath`; malformed pointers are -usage errors and unknown effective/historical paths are operational lookup -failures. Do not treat a native writer's empty output as successful lookup. - -Text defaults to the owning `WriteExplanation` rendering. Use -`--format yaml` with `{scope, path, effective, origin, history, secret_reference}`. -Preserve `present`, `redacted`, and the owner's YAML fragment in each value -snapshot; represent fragments as strings so absence/null/masked values remain -unambiguous. Canonicalize paths through public `Path.String()`. Preserve owning -provenance, reasons, dependencies, and reference names, not credential values. - -**Provider requirements:** safe public explanation and native text writer. -**Depends on:** INT-01, CFG-01. **Completion evidence:** known current and removed -historical paths work, root-pointer presence works, invalid/missing paths have -distinct outcomes, and safe snapshots survive YAML report conversion. - -### PK-01: PromptKit configuration integration - -The bundled helper acquires an engine through the application callback, then -uses `Engine.InspectConfiguration()` and its public native writers, sources, -diagnostics, and explanation methods. Register these capabilities under the -`promptkit` scope. Registration of this scope neither requires nor implicitly -installs definition inspection. - -**Provider requirements:** engine/configuration-inspection acquisition. -**Depends on:** INT-01, CFG-01–05. **Completion evidence:** native PromptKit YAML -and ConfigKit-compatible provenance are exposed through the standard family; -aggregate show can combine it with `app` without translating either document. - -### PK-02 and PK-03: named definition inspection - -Use these command inputs: - -```text -app promptkit show prompt ID [--version VERSION] [--format text|yaml] -app promptkit show profile ID [--format text|yaml] -``` - -Both acquire the engine lazily and pass the invocation context to the public -inspection method. Prompt-version omission follows PromptKit's own selection -semantics. Missing named definitions are operational lookup failures. These -operations do not render/execute prompts, resolve credential values, or generate -model output through CommandKit's handlers; application acquisition retains its -own behavior. - -Prompt reports include ID, selected version, opaque hash, declared default profile, -input definitions in declaration order, and declared output contract. Use explicit -YAML fields rather than depending on incidental Go struct serialization. An -output-contract value of `json` is domain metadata, not a JSON report format. - -Profile reports include the named ID, backend-completed effective target fields, -`ExtraParams`, credential environment-variable name, and direct-credential -requirement from the existing public `ProfileInspection` result. `ExtraParams` -contains provider settings and is included in both text and YAML reports. It -requires no additional redaction or upstream inspection API for this feature. -Preserve nested parameter values when projecting the public result into the -CommandKit report schema. Credential values remain separate from these settings. - -**Provider requirements:** public `InspectPrompt`/`InspectProfile` respectively; -each capability can be registered independently. **Depends on:** INT-01 and the -public report projection. **Completion evidence:** text and YAML preserve public -metadata and effective provider parameters; profile credentials are reported as -requirements/references; unknown IDs and cancellation retain supported public -error identity; help never constructs an engine. - -## Selectors, reports, and ownership - -Use a shared standard selection input for acquisition-bearing inspection -commands, carrying presence-aware `--config` and singleton `--overlay`. -Application callbacks interpret their values using the owning loader. Omission -delegates discovery/default selection; an explicitly empty overlay can represent -the loader's no-overlay selection. The application -supplies schema, filesystem/source construction, imports, and domain resolution. -PromptKit integration does not assume its configuration is at the application -root path; its callback maps selectors to its acquisition path. - -Register application context flags through typed bindings with declared scope -applicability. For example, a Narratio campaign selection can matter to `app` -inspection and to engine acquisition derived from that application view. Reject -explicit selectors that do not apply to any selected scope with a usage diagnostic; -for `all`, route each selector to the scopes that declare it. Metadata/help should -state applicability. Validate declared selector combinations before acquisition; -domain lookup/validation remains operational. Do not infer application-specific -campaign or session policy. - -Use text defaults for CommandKit-owned summaries and YAML alternatives; -`config show` is native YAML. CommandKit owns report schemas for summaries, -source/explanation projections, and definition reports. Owning libraries own the -native documents and safe values. Select schema fields deliberately and document -them with implementation; no separate schema-version integer is proposed. - -| Responsibility | Owner | -| --- | --- | -| Command paths, shared grammar, standard handlers, metadata/help, selection preflight, report framing, outcomes | CommandKit | -| Typed custom input mechanics and routing | CommandKit; custom domain meaning remains with the application | -| Configuration composition, recorded resolution, provenance, sensitivity, native effective/explanation rendering | ConfigKit/PromptKit through supported public APIs | -| Source discovery, application schema and domain validation/resolution, engine construction, runtime dependencies | Application callbacks | -| Custom session/execution commands, effects, outputs, and domain results | Application | -| Process context/signals, streams, final status mapping, process exit | Application entry point | - -Safe owning-library inspection is required for enabled standard operations. This -does not promise that arbitrary configuration or prompt content is suitable for -public disclosure, and CommandKit does not inspect arbitrary consumer error -objects to enforce a broader confidentiality policy. - -## Upstream capability evidence - -The following clean sibling revisions were reviewed on 2026-10-07. They are -evidence snapshots, not build dependencies. - -| Repository | Reviewed revision | Released API baseline | -| --- | --- | --- | -| ConfigKit | `dc09959cca4e105f49ec316c6d4ba585bd2340bd` | v0.5.0 | -| PromptKit | `4b8169da286917fde7875425bb32b799b12c6af3` | v0.12.0 | -| Scriptorium | `723fee9c466789fd3b6cca5492bf2edf99f4136c` | Consumer evidence | -| Notarius | `66fa5585c1190581e96ec42102ce745c3869ba6d` | Consumer evidence | -| Narratio | `8afb49c01808c04bc73f782d1619e87c8c2cd312` | Consumer evidence | -| Audita | `3b4933256eff84327b812e7ae12babf743bc04a6` | Consumer evidence | - -| Capability | ConfigKit v0.5.0 | PromptKit v0.12.0 | Delivery consequence | -| --- | --- | --- | --- | -| Validated acquisition | `Load`/recorded resolution with application definition | `NewEngine` and application acquisition | Include CFG-02; do not add a parallel validator. | -| Native effective YAML | `Result[T].WriteEffective` | `ConfigurationInspection.WriteEffective` | Include CFG-03 and PK-01. | -| Sources/diagnostics | Public result/load-error source and diagnostic records | Configuration-inspection sources/diagnostics | Include CFG-04 and OUT-01. | -| Safe path explanation | `Explain`, `WriteExplanation`, public `Path` | Equivalent configuration-inspection methods | Include CFG-05. | -| Named prompt metadata | Outside its resource domain | `Engine.InspectPrompt` and `PromptInspection` | Include PK-02. | -| Named effective profile target | Outside its resource domain | `Engine.InspectProfile` exposes the effective target including copied `ExtraParams`, plus credential requirements/reference names | Include PK-03 using the existing public result, including provider parameters. | -| Catalog enumeration | Outside its resource domain | No public prompt/profile enumeration API found | Defer CAT-01; recommend upstream captured catalog inspection. | -| Safe full semantic comparison snapshot | No dedicated public structured tree plus full sensitivity/coverage contract found | No corresponding configuration snapshot API found | Defer DIFF-01; recommend upstream safe snapshot support. | - -Relevant public declarations are [ConfigKit inspection](../../../ConfigKit/inspection.go), -[metadata](../../../ConfigKit/metadata.go), [PromptKit configuration inspection](../../../promptkit/configuration_inspection.go), -[engine methods](../../../promptkit/engine.go), and [inspection types](../../../promptkit/types.go). -ConfigKit's `HistoricalPaths`, `Explain`, and redacted YAML provide useful pieces; -they do not expressly define the full comparison representation required by ADR -0008. Deriving a comparison contract from these pieces would require an explicit -owning-library agreement and design, rather than assuming masks imply equality. - -### Deferred capability targets - -- **DIFF-01:** acquire two independently resolved selections of one scope through - public safe snapshots. Preserve absent/null/empty distinctions and scalar - semantics, recursively compare mappings, compare ordered sequences atomically, - apply sensitivity union, and report differences plus gaps in text/YAML. Completed - comparisons succeed even with differences/gaps. Snapshot data must describe - hidden paths and supported reasons without fetching secrets. Comparison selector - syntax/inheritance must be decided when bringing this feature into delivery. -- **CAT-01:** list captured prompt/version entries and named profiles through public - owning catalog APIs; deterministic reports describe actual loaded definitions. - Do not infer catalogs from configuration YAML or inspect sibling internals. - -Do not create empty handlers, pretend capabilities, or unused public snapshot -types for these deferred targets. Future upstream contracts should inform their -representations. Future FeedKit-like families can supply appropriate operations -without supporting comparison or configuration scopes. - -## Reuse assessment and consumer fit - -Use the reviewed revisions above to evaluate extraction; no source is copied by -this roadmap. Prefer existing public owning writers over porting their renderers. - -| Candidate | Useful behavior | Adaptation and boundary | -| --- | --- | --- | -| [Notarius configuration handlers](../../../notarius/internal/cli/configkit_commands.go): `runConfigEffective`, `runConfigExplain` | Load an application result and call native ConfigKit writers; canonical path parsing and lookup handling | Retain the acquisition-to-writer pattern. Replace application scopes, manual flag sets, output/status handling, and loader coupling with INT-01/CFG-03/05. The application keeps its loader and domain selection. | -| Same file: `runConfigProfile`, `runConfigValidate` | Named profile inspection and application-specific validation examples | Evaluate inputs and callback needs. Their JSON report, private wrappers, and runtime/domain validation are not standard contracts. | -| [Scriptorium inspection dispatch](../../../scriptorium/internal/adapter/cli/inspect.go): `inspectCommand` | Lazy engine acquisition and named inspection followed by formatting | Keep upstream method use. Replace private dispatch, `context.Background`, output-file behavior, old command paths, and integer-status plumbing with caller context, streams, and outcomes. | -| [Scriptorium report projections](../../../scriptorium/internal/format/inspection.go): `FormatPromptInspection`, `FormatProfileInspection` | Explicit prompt/profile field projection and readable presentation | Prompt/profile DTO fields are useful starting inventories. Replace JSON output with YAML and include the public effective `ExtraParams` values in profile reports. | -| [Narratio comparison](../../../narratio/internal/app/config_diff.go): `ConfigDiff`, `configDiffWithDependencies` and comparison helpers | Independent resolved selections, deterministic path records, and add/remove/change presentation | Evidence for future DIFF-01. Its application projection/digests, overlay-only operands, shared campaign policy, and absence of ADR 0008 sensitivity-gap semantics require redesign; no initial direct port is proposed. | - -Recommend implementing the small integration glue from these public contracts, -using consumer code as behavioral evidence. If a substantive helper or fixture is -actually copied/adapted, record its source commit, affected symbols/files, -modifications, and required notices when it lands. Scriptorium and Notarius grants -are GPL-3.0-or-later; CommandKit is LGPL-3.0-or-later. Common ownership does not by -itself change those grants. Resolve applicable reuse rights or an author's -deliberate licensing choice before any such copy under the -[OSS policy](../policy/oss.md). No blanket source-port permission is inferred. - -Use secret-free synthetic fixtures reflecting existing consumer scenarios: -defaults plus overlays and historical deletion, inherited profiles, explicit -zero/false selectors, missing definitions, and a second scope that fails during -aggregate show. Existing consumer cases can inform these fixtures; entire -application schemas/workspaces need not be imported. - -Two maintained public examples should substantiate infrastructure reduction: - -1. **Simple ConfigKit consumer:** register one application loader and its schema, - use bundled scope wiring, then register a typed custom command. Standard help, - parsing, validation, native show, sources, and explanation need no private CLI - handlers or formatters. -2. **Complex consumer modeled on Narratio/Scriptorium:** register app and PromptKit - scopes plus named definition inspection, with typed campaign/context selection; - compose app → engine acquisition in consumer code; retain a custom - `session restore` group/handler. Standard paths and report composition remain - CommandKit-owned while campaign/session meaning stays with the application. - -The declaration and callback burden should demonstrate infrastructure reduction -against the existing handlers. Consumers should be able to use these examples -without recreating dispatch, standard input parsing, or standard report projection. - -## Explicit deferrals - -In addition to DIFF-01 and CAT-01, defer JSON report -output, shell completion, output-file management, backend selection, a plugin -framework, general dependency injection, concurrent-dispatch guarantees, and -implementation of additional library families. None is needed to prove the -initial selected feature target. Application-owned commands remain extensible. - -Consumer migrations and source publication were kept outside the initial -library target. ReleaseKit adoption is complete; current release operations -are in the [maintainer procedure](../release.md). The completed adoption record is -available at the [historical adoption revision](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/c0c03285f7beac3e96f1708b655c1eb2add35e79/docs/roadmap/implementation.md). -The initial implementation targeted a usable module with maintained examples; -it did not create placeholder publisher commands or a binary build matrix. - -## Completion criteria - -The initial target is complete when the included feature IDs have their stated -observable behavior and evidence, and the selected roadmap choices are reflected -consistently in the API and CLI contracts. - -Use proportionate deterministic, offline behavioral evidence under the -[testing policy](../policy/testing.md): public consumer tests with the real adapter -for grammar/presence/state, real local ConfigKit/PromptKit fixtures for inspection, -and controlled acquisition/writer failures at those boundaries. Review the public -type/dependency boundary directly; choose automation only where its distinct -protection justifies maintenance. Do not retest complete upstream libraries or -add blanket coverage, race, scanner, or platform gates. - -Maintain these substantive documents/artifacts as implementation lands: - -- GoDoc for exact exported contracts, ownership, errors, and lifecycle. -- `docs/cli.md` for installed standard syntax, formats, scope coverage, and outcomes. -- Consumer guidance and complete simple/complex examples; link to owning upstream - configuration contracts instead of duplicating schemas. -- `docs/internal/overview.md` describing the two implemented packages and their - actual boundary. Add focused internal/integration documents only where useful. -- Dependency/source attribution and applicable license/notice material in the - change that incorporates it, under the OSS policy. -- Contributor commands and orientation updates once the Go module and validation - commands actually exist; preserve existing policy ownership. diff --git a/docs/roadmap/performance.md b/docs/roadmap/performance.md deleted file mode 100644 index 1d9ba1f..0000000 --- a/docs/roadmap/performance.md +++ /dev/null @@ -1,268 +0,0 @@ -# Computational efficiency roadmap - -Status: implemented; PF-01–PF-06 and selected approaches OD-1/OD-2 are complete. - -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 target state, priorities, and selected implementation -scope. The completed [implementation record](implementation.md) owns ordered -stages, measurement fixtures, validation, and execution 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 | Target result | Primary benefit | -| --- | --- | --- | --- | -| PF-01 | PromptKit text reports are built even for YAML requests. | Render only the requested format and avoid redundant report buffers. | Inspection CPU and allocation reduction | -| 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. | Wide or deeply nested command trees | -| PF-03 | Every invocation translates and sorts metadata; help and usage construct another backend tree. | Reuse immutable metadata and the invocation's prepared tree. | Repeated execution and help/usage paths | -| 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. | Large or newline-dense reports | -| PF-05 | Each registration copies the existing top-level registry. | Prepare new entries separately and install a validated batch atomically. | App construction with many registrations | -| PF-06 | Scope ordering, lookup, and selection repeat; selector duplicate checks scan previous entries. | Prepare stable scope metadata once and use direct duplicate checks. | Growing scope and selector sets | - -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. - -## Target 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. - -The target selects the requested formatter before rendering and delivers the -completed report without a redundant intermediate text buffer. It retains the -existing structured report representation and YAML encoder, including -`ExtraParams`, diagnostics, and delivery-failure semantics. YAML requests produce -only the structured report; text requests produce only the text report. - -### 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. - -The target provides direct backend-to-declaration lookup and reconstructs only -the selected path from parent relationships inside the adapter. Declaration -lookup is constant time, with path construction proportional to D after tree -preparation. Exact registered-path matching and error classification are retained. -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. - -The target retains the invocation's prepared backend tree inside the adapter for -parsing, help, and usage. The root coordinates these operations through a narrow -internal handle without receiving Cobra/pflag objects. Immutable bridge metadata -and sorted child order are cached per `App` and refreshed when registration -changes the declared tree. Failed registration leaves existing 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. -Efficiency evidence distinguishes both cases, including 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. - -The target analyzes the preamble with byte offsets and stops when the directive -or marker decision is complete. Directive detection and scope-label placement -share that analysis. Framing needs no document-wide line index or 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. - -This target removes avoidable scans and allocations; complete rendering and -delivery 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. - -The target prepares owned pending declarations and checks collisions against -existing and pending entries before changing the registry. Successful batch -validation installs the pending entries without copying existing map entries, -while preserving declaration ownership and atomic validation. Its completion -point also invalidates derived metadata for PF-03 when the tree changes. - -Batch registration remains an optional consumer optimization. Both individual -and batch registration are supported by this target. - -### 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. - -The target retains normalized declarations, stable scope order, direct name -lookup, and discovery inventory as private registered-suite metadata. Selector -duplicate validation uses direct name and short-name checks. Context projection -and selection validation remain fresh for each invocation; both preflight and -handlers can consult the same prepared metadata without repeated sorting or -quadratic scope searches. - -Scope order, declared operation availability, and scope-aware selector validation -remain governed by [ADR 0009](../adr/0009-configuration-scopes.md). Metadata -preparation leaves acquisition and runtime context callbacks uninvoked. - -## Delivery scope and evidence - -PF-01 through PF-06 are included in the implementation target. Conditional -formatting, indexed ancestry, and YAML preamble analysis address the clearest -redundant work. Registry and scope preparation are lower-priority, bounded -changes that remove observed scaling costs without adding consumer requirements. -The [implementation plan](implementation.md) specifies the concrete mechanisms -and divisions of work. - -Efficiency evidence compares elapsed cost, bytes allocated, and allocations per -operation for representative dispatch, reports, registration, and scope sizes. -It distinguishes cold and repeated execution, isolated and complete command -costs, provider work, and memory retained by caches. Source analysis alone does -not establish a measured speedup. Measurements establish no fixed timing -threshold, public allocation budget, or additional release gate. - -Implementation preserves existing public API and CLI contracts. Internal -documentation describes the changed mechanics when they land; detailed -validation and before/after evidence belong in the implementation plan. - -Selected-scope memoization and additional selector-membership indexes are -deferred pending evidence that their bookkeeping is worthwhile. Mutable backend -reuse across invocations and segmented YAML delivery are outside the selected -target; future reconsideration needs a deliberate change to OD-1 or OD-2. - -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. diff --git a/docs/roadmap/releasekit.md b/docs/roadmap/releasekit.md deleted file mode 100644 index b911546..0000000 --- a/docs/roadmap/releasekit.md +++ /dev/null @@ -1,247 +0,0 @@ -# ReleaseKit v0.3.0 upgrade roadmap - -Status: implemented; ReleaseKit v0.3.0, Go 1.26.0 minimum, and Go 1.26.8 -release toolchain are in place. - -Date: 2026-10-08. - -## Purpose and authority - -Upgrade CommandKit's maintainer publication tool from ReleaseKit v0.2.0 to -v0.3.0 and simultaneously raise CommandKit's declared Go consumer minimum to -1.26.0. The user has accepted both changes. Retain the existing root-module Go -tool dependency and source-only publication workflow. - -This document records the target state, completed upgrade work, and evidence -from the reviewed baseline. The -[release policy](../policy/release.md), -[architecture policy](../policy/architecture.md), -[agent policy](../policy/agents.md), -[testing policy](../policy/testing.md), and -[documentation policy](../policy/documentation.md) govern the work. Apply the -[OSS policy](../policy/oss.md) to any changed attribution or incorporated material. -The [maintainer procedure](../release.md) owns current release operations. - -This is a new upgrade roadmap. The completed initial ReleaseKit adoption is -available in Git history; its retired assignments are not part of this work. -Implementation completion is distinct from publishing a CommandKit release. - -## Reviewed baseline - -CommandKit was reviewed at `7eebe877cf9a21fb4f886f89bbc2089661237fc1` with a clean -worktree. ReleaseKit v0.3.0 identifies commit -`e43df4416e0ed987349b2ea04a2c68c25e552772`; the local checkout and published tag -matched that revision during review. Its [release notes](https://gitea.maximumdirect.net/eric/ReleaseKit/src/commit/e43df4416e0ed987349b2ea04a2c68c25e552772/docs/releases/v0.3.0.md) -record the compatibility and upgrade guidance. - -| Area | Reviewed baseline | Target | -| --- | --- | --- | -| Module | `go 1.25.5`; ReleaseKit v0.2.0 selected through a `tool` directive and module requirement. | `go 1.26.0`; the same CLI tool dependency selects ReleaseKit v0.3.0. | -| Release toolchain | Go 1.25.5 selected in the runbook. The review environment has Go 1.26.8. | Go 1.26.8, documented separately from the Go 1.26.0 consumer minimum. | -| Launcher | `scripts/release` builds the module-selected native CLI in readonly mode and delegates publication with argument, status, and stream preservation. | The same bootstrap and delegation use v0.3.0 under the selected compatible toolchain. | -| Profile | `releasekit.json` specifies product, remote, and expected push endpoint; validation uses the default suite. | The same minimal source-only profile. | -| Evidence | Deterministic launcher tests and an opt-in publication exercise against disposable local Git repositories exist. | Those boundaries work with the upgraded module selection and toolchain. | -| Documentation | Policy, runbook, and consumer guide describe v0.2.0 and/or the Go 1.25.5 selection. | Canonical owners describe the implemented upgrade and its consumer impact. | - -The upstream CLI, profile schema, and public signatures are unchanged. ReleaseKit -itself raises its minimum from Go 1.25.0 to 1.26.0; its dependency versions are -unchanged from v0.2.0. The original planning review did not run a test suite or -publication exercise; completed upgrade validation is recorded below. - -## Target end state - -### Module selection and Go compatibility - -The root [go.mod](../../go.mod) declares **Go 1.26.0** and selects -**ReleaseKit v0.3.0** for `gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit`. -The corresponding [go.sum](../../go.sum) records the resolved checksums. The -existing tool declaration retains the executable through ordinary module tidy. - -The tool shares CommandKit's module graph, so the new minimum applies to library -consumers as well as maintainers even though production packages do not import -ReleaseKit. This is an intentional compatibility change. Go 1.25 consumers need -to upgrade before adopting the CommandKit revision containing it. - -The consumer minimum remains the initial stable release of the Go 1.26 series. -A newer release-validation patch does not raise that floor by itself. The -[release policy's toolchain rules](../policy/release.md#consumer-minimum-and-release-toolchain) -define the support presumption and compatibility treatment. No additional -minimum-version test matrix or promise of identical results across toolchains -is introduced. - -### Ownership and publication behavior - -ReleaseKit remains maintainer tooling. The root `commandkit` facade and internal -Cobra adapter keep their existing responsibilities; this upgrade adds no runtime -ReleaseKit import, public wrapper, or operator-facing command family. - -The existing launcher remains the publication entry point. It builds the native -CLI from the committed module selection with readonly metadata and automatic -workspace/toolchain switching disabled. The maintainer's selected `go` on `PATH` -is used for bootstrap and candidate validation. A `toolchain` directive is not -needed to make this launcher select that executable; setup belongs in the runbook. - -CommandKit continues to publish an annotated source tag after its candidate is -available on the authoritative branch. ReleaseKit owns validation, publication -guards, tag creation, and publication outcome reporting. CommandKit owns the -candidate, version, note, profile, and runbook. Successful publication remains -separate from optional delivery investigations under the existing release policy. - -### Benefits within the selected scope - -ReleaseKit v0.3.0 reduces output-copying and retention during Go command -execution, preserving full failure diagnostics and underlying causes. That -improvement benefits CommandKit's default candidate suite. - -The upstream Git reader, file-check caches, cancellation cleanup, asset hashing, -and runtime-version improvements remain upstream responsibilities. Our current -profile does not enable optional committed-file checks or hosted artifact -delivery. Their improvements are available if those capabilities are deliberately -selected later; this upgrade does not enable them. No CommandKit latency or -allocation target is part of adoption. - -## Completed upgrade work - -### Module and toolchain alignment - -- [x] Select Go 1.26.8 under OD-1 and document its installation - and `PATH` setup in the runbook. Use that toolchain for upgrade validation and - subsequent release tasks governed by the procedure. -- [x] Upgrade the existing CLI tool dependency to v0.3.0 and set the Go directive to - exactly 1.26.0 using ordinary Go module tooling. Review the resulting module - and checksum changes, including any automatically generated toolchain metadata. - Keep the consumer floor separate from the maintainer patch selection. -- [x] Prepare dependencies before offline validation. The local sibling checkout is - review evidence, not a replacement module or build prerequisite. Diagnose any - checksum failure using upstream guidance and retain checksum verification. -- [x] Review incidental module changes. ConfigKit, PromptKit, and backend upgrades - are separate work; v0.3.0 does not require new versions of its own dependencies. - -### Launcher and profile verification - -- [x] Confirm the existing launcher builds the upgraded native executable from the - module-selected package and preserves publication arguments, streams, and - statuses. Confirm that the executable identifies ReleaseKit v0.3.0. -- [x] Retain the current profile and launcher design. Change implementation only if - a demonstrated compatibility issue requires it; no migration is indicated by - the reviewed upstream CLI or schema. -- [x] Reuse existing launcher tests. Adjust fixtures only where the selected version - or Go requirement actually affects their behavior. An older version string - used to test rejection of an independent package pin need not be replaced just - because the adopted version changes. - -### Canonical documentation and provenance - -- [x] Update [docs/policy/release.md](../policy/release.md) to identify the selected - ReleaseKit version while retaining its v1.6 upstream provenance and local - source-only rules. This tooling upgrade is not another policy-template adoption. -- [x] Update [docs/release.md](../release.md) with the selected Go 1.26 patch, - executable setup commands, and v0.3.0 source-pinned upstream references. Keep - versioning rules in the policy and operations in the runbook. -- [x] Update the [consumer guide](../consumers/guide.md#go-compatibility) to explain - the Go 1.26.0 minimum and shared tool-module reason. The current attribution - of the floor to PromptKit's Go 1.25.5 requirement becomes obsolete. -- [x] Check contributor navigation and current references affected by the upgrade. - Historical planning records and immutable release notes retain their original - facts; avoid replacing every historical version string. -- [x] Apply the [OSS policy](../policy/oss.md) to the actual material scope. Tool use - alone does not require a new attribution entry. Update entries or license links - if incorporated material or dependency selection changes require it. - -### Validation and completion evidence - -Use the existing validation boundaries rather than adding recurring release gates: - -- [x] Run the deterministic offline default suite under the selected toolchain, - covering the public library and native launcher behavior. -- [x] Exercise the existing opt-in local publication test with the upgraded module - selection after cache preparation. It covers a real native bootstrap, exact - candidate tag publication to a disposable bare repository, one candidate suite, - clean fixture state, and endpoint-mismatch preflight. Keep it opt-in in normal - development and publication; this is upgrade evidence, not a new release gate. -- [x] Inspect production package dependencies to confirm ReleaseKit remains outside - the root library and internal adapter import closures. Review module selection - and CLI version evidence separately from that runtime boundary. -- [x] Review canonical-document changes, local links/fragments, provenance, and - whitespace. Record the actual toolchain, resolved module revision, checks run, - outcomes, and any qualifications when marking this roadmap implemented. - -The [developer guide](../development.md#release-tooling-development) owns the -existing local exercise commands. Reuse successful evidence for unchanged -content; adding a benchmark requirement, platform matrix, or upstream suite -rerun is not necessary to establish this upgrade's selected behavior. - -## Completion criteria - -The upgrade is implemented when the root module selects v0.3.0 with Go 1.26.0, -the documented release toolchain can bootstrap and validate it, existing -launcher/publication behavior has the stated evidence, and current documentation -accurately describes the minimum and ownership boundaries. Release notes carry -the compatibility explanation when a release containing the change is prepared. - -This work does not publish CommandKit, add hosted delivery, split tooling into a -second module, or change standard CLI/API semantics. Actual publication and its -fresh version-matched note remain a separate release-preparation task. - -## Completion evidence - -Implemented from `efc5065` using Go 1.26.8 on Linux/amd64. The module now -contains `go 1.26.0`, the retained CLI tool declaration, and the ReleaseKit -v0.3.0 requirement/checksums. Module tidy retained that selection. No other -dependency versions changed and no toolchain directive was added. The downloaded -module's origin identifies the reviewed `e43df4416e0ed987349b2ea04a2c68c25e552772` -tag revision; dependency preparation required no checksum repair. - -Validation completed: - -- Default suite: `go test -mod=readonly -count=1 ./...` passed with `GOWORK=off`, - `GOTOOLCHAIN=local`, `GOPROXY=off`, `GONOPROXY=none`, and `GOSUMDB=off`. - This includes public library and deterministic launcher tests; existing test - sources were sufficient and unchanged. -- The existing local publication exercise passed with - `COMMANDKIT_RELEASE_INTEGRATION=1` and the same offline settings: - `go test -mod=readonly -count=1 ./scripts -run '^TestReleaseIntegration$' -v`. - It published only within disposable repositories and proved the candidate, - single suite execution, clean fixture, and endpoint-mismatch behaviors above. -- A native CLI was built in ignored `.releasekit/bin/` storage with the launcher's - host-target and readonly settings. Its `version` output was `releasekit v0.3.0`; - `go version -m` identified Go 1.26.8 and the module-selected v0.3.0 build. -- `go list -mod=readonly -deps` for the root package and `internal/cobra` found no - ReleaseKit, Goldmark, or `golang.org/x/mod` runtime imports. The launcher and - profile were unchanged. ReleaseKit remains tool-only material; no attribution - entry or copied source was added under the existing OSS policy. -- The runbook, release policy's local tool selection, consumer compatibility - explanation, and contributor navigation now describe the upgrade. The - release policy remains based on v1.6 at its existing upstream revision. - Local documentation destinations/fragments, shell snippet syntax, and - whitespace checks passed. - -This verifies the upgrade without publishing CommandKit or establishing an -additional recurring release check. No upstream benchmark or test suite was -rerun; the evidence concerns CommandKit's selected integration. - -## Release preparation follow-up - -The next CommandKit release note must explain the Go minimum increase and -required consumer action. Its CommandKit version is selected during release -preparation under policy, with the matching note and footer. That separate -publication task was not performed or authorized by this upgrade; the current -consumer guide already explains the compatibility change. - -## Selected decisions - -### OD-1: release-validation patch version - -**Resolved: Go 1.26.8, accepted by the user and implemented.** It is the -toolchain available in the review environment and used by ReleaseKit v0.3.0's maintainers. Using it avoids -an additional installation in that environment and benefits from later patch -updates within the selected Go series. Declare `go 1.26.0` for consumers and -document 1.26.8 as the runbook's release-toolchain selection. The adopted -policy permits same-series support to be presumed from this validation; a -second mandatory run on 1.26.0 is unnecessary absent a concrete concern. - -**Alternative considered: Go 1.26.0.** It validates directly at the consumer floor -and makes the minimum and release toolchain identical initially. It requires -installing that patch in the reviewed environment and forgoes subsequent patch -updates. It is viable if direct minimum-toolchain validation is preferred, but -the current policy does not require that extra alignment. diff --git a/docs/roadmap/remediation.md b/docs/roadmap/remediation.md deleted file mode 100644 index 9627437..0000000 --- a/docs/roadmap/remediation.md +++ /dev/null @@ -1,138 +0,0 @@ -# Performance implementation review findings - -Status: R-01 complete; all recorded remediation work is addressed. - -Date: 2026-10-09. - -## Review scope and authority - -Reviewed the performance implementation at `18ff0d6`, covering the changes after -`1274ae7` against the [efficiency target](performance.md), selected OD-1/OD-2 -approaches, [implementation record](implementation.md), accepted -[ADRs](../adr/), and applicable architecture, agent, and testing policies. - -The completed ReleaseKit review findings remain available in -[Git history](https://gitea.maximumdirect.net/eric/CommandKit/src/commit/18ff0d6/docs/roadmap/remediation.md). -Release tooling is outside this implementation review. - -## Architecture assessment - -The selected structure is present: - -- The root facade owns declarations, registration, typed inputs, standard - handlers, and invocation outcomes. Cobra and pflag remain inside the internal - adapter; the changes add no exported API declarations. -- Each `App` lazily retains immutable neutral command metadata. Successful - nonempty registration invalidates it; failed and empty registrations leave - it intact. Pending declarations are validated and cloned before installation - without copying the previously installed registry. -- Each invocation prepares a fresh mutable adapter session, reusing it for - parsing, help, and usage. Presentation can refresh metadata after callback - registration without rerunning input callbacks. Backend commands map directly - to declarations; parent links reconstruct the selected path. -- Configuration registration prepares ordered scopes, name lookup, installed - operations, and discovery metadata. Invocation contexts and acquisition remain - live callbacks. PromptKit builds the requested report format, and aggregate - configuration framing scans only the YAML preamble while retaining the - selected full native and framed buffers. - -These changes implement PF-01–PF-06. The review identified an ownership -regression in the session integration, corrected under R-01 below. The -[internal overview](../internal/overview.md) owns the maintained package inventory. - -## R-01: restrict built-in help interception to the root command - -**Priority:** high. **Category:** dispatch correctness, application ownership, -and unintended restriction. - -**Location:** [execute.go](../../execute.go), `App.Execute`, line 45 at the -reviewed revision. Introduced by `a7960e5`. - -The dispatcher selects a leaf declaration and then checks `command.name == -"help"` to identify the built-in help operation. That matches an application -command named `help` at any depth. Its ordinary typed input is then asserted to -be CommandKit's private `*helpInput`, producing an operational failure instead -of invoking the registered application handler. - -A public API reproduction created a runnable `help` command with `struct{}` -input, composed it beneath the application-owned `session` group, and passed the -group to `New`. Construction and registration succeeded. Execution produced: - -```text -args=[session help] kind=operational status=1 cause=built-in help input has an unexpected type handlerCalls=0 -args=[help session] kind=success status=0 cause= handlerCalls=0 -args=[session help --help] kind=success status=0 cause= handlerCalls=0 -``` - -The first invocation must reach the application handler. The remaining two are -metadata help requests and appropriately leave that handler uninvoked. - -[ADR 0001](../adr/0001-command-dispatch-and-inputs.md#ownership-and-namespace-structure) -and the [architecture policy](../policy/architecture.md#command-and-application-ownership) -leave custom names and semantics with applications outside standard families. -[ADR 0006](../adr/0006-command-grammar.md) also encourages consistent verbs, -including `help`. The selected session integration specifically concerns the -reserved **top-level** help command. Matching only the leaf name effectively -introduces a global reservation of that name, although registration still -accepts it. No such additional restriction was selected. - -Required work: - -- [x] Identify the root built-in help command by its complete selected path - or an equivalent explicit reserved-command identity. A root-path check such - as `len(parsed.Path) == 1 && parsed.Path[0] == "help"` is sufficient for the - current registry. Other runnable declarations must continue to their handler. -- [x] Add a public behavior regression for an application-owned nested `help` - command. Verify it receives its typed input and that its handler outcome is - preserved. Keep local `--help` and `help session help` as metadata operations. -- [x] Retain existing root help, invalid-target, usage, fresh-invocation, - registration-refresh, and diagnostic behavior. Use existing coverage where - sufficient; verify the relevant regression and default suite after the fix. - -Do not remediate this by rejecting nested `help` names or imposing new command -naming rules. Keep the session optimization and established ownership boundary. -Mark this item complete only after the correction and its evidence are recorded. - -### Completion evidence - -**Completed:** `App.Execute` now recognizes the built-in help command only when -its selected path is the root `help` command. Nested application commands keep -their existing handler path and naming freedom; session reuse is retained. - -The public regression `TestExecuteRunsApplicationOwnedNestedHelp` verifies a -required typed operand reaches the nested handler and preserves its domain, -status, and cause. Local `session help --help` and explicit `help session help` -render the command's metadata without invoking that handler or requiring its -execution operand. - -The regression first failed against the original dispatcher with the reported -unexpected-input-type failure and passed after the correction. Focused validation -and the full default suite passed with readonly, offline module access: - -```sh -GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -count=1 . -run '^TestExecuteRunsApplicationOwnedNestedHelp$' -GOWORK=off GOTOOLCHAIN=local GOPROXY=off GONOPROXY=none GOSUMDB=off go test -mod=readonly -count=1 ./... -``` - -Existing root help, invalid-target, usage, fresh-invocation, registration-refresh, -and diagnostic tests passed. Changed Go files were formatted; document links -and whitespace checks passed. No new public contract or command-name restriction -was introduced. - -## Original review evidence and limits - -- Reviewed the production diffs, changed behavioral tests, benchmark fixtures, - architecture documentation, and completion/measurement records. Traced cache - invalidation, session refresh, input preparation, scope lookup, acquisition, - YAML framing, and requested-format delivery. -- Executed the public consumer reproduction above from a temporary file outside - the repository with readonly, offline module access. No repository test or - production code was added or changed during this review. -- The implementation record reports a successful default suite at `62b4a48`, - the last production-code revision. This review did not rerun that suite or the - benchmarks. Allocation improvements and registration tradeoffs are documented - there; its final cross-run timing comparison is explicitly inconclusive under - differing host load. This review does not establish a latency guarantee. -- No other issue requiring remediation was identified in the reviewed scope. - The changes do not establish concurrent dispatch, application startup rules, - provider-result caching, new release gates, or additional public API promises.