Files
commandkit/docs/policy/architecture.md

7.9 KiB

Architecture Policy

Base Policy Version: 1.3

Last Updated: 2026-10-06

Upstream Source: architecture.md

Purpose And Ownership

CommandKit is an opinionated Go library for standard inspection commands, consistent CLI syntax, and reduced application command infrastructure. This policy owns normative responsibility boundaries, dependency direction, and architectural constraints. ADRs own decision rationale; the implementation roadmaps own proposals, sequencing, and implementation status.

Architectural constraints govern future implementation. Concrete package inventory and mechanics belong in internal documentation when implemented. Exact exported contracts belong in Go declarations and GoDoc; implemented operator behavior belongs in the CLI reference. Do not describe planned packages or APIs as existing implementation.

Success Criteria

Evaluate designs and adoption against both criteria:

  1. Applications adopt consistent command vocabulary, syntax, and inspection behavior for the standard suite.
  2. Applications remove substantial repeated CLI infrastructure while keeping clear ownership of domain behavior.

Existing applications supply evidence of needs, not compatibility requirements for CommandKit. Adoption is expected to make breaking changes to divergent consumer conventions. Once CommandKit publishes its own contracts, changes to those contracts follow the release policy.

Use representative simple and complex consumers to substantiate API designs. Replacing parsing and dispatch plumbing with equally repetitive registration or callback bookkeeping does not satisfy infrastructure reduction. Keep enough flexibility to express genuine application requirements within one command model.

Command And Application Ownership

ADR 0001 records the selected CommandKit-owned dispatcher, per-instance registry, and typed-input model.

CommandKit owns dispatch, common parsing, presence tracking, help, shared syntax diagnostics, and the handlers and observable contracts of its standard families. Applications register domain commands outside those families and own their meaning, effects, domain validation, artifacts, and operational outcomes. Namespaces provide the ownership boundary: standard config and an installed promptkit family remain CommandKit-owned. Applications do not replace their handlers or add private operations beneath them.

Applications own their executable entry points, context creation, signals, stream selection, runtime construction, and final process exit. CommandKit returns invocation outcomes and must not terminate the process. Its common mechanics apply to custom commands without taking ownership of their domain semantics or success-report formats.

Use explicit instance construction and composable command registration, not package-global or import-time registries. One definition supplies routing, parsing, and help metadata. Duplicate paths and attempts to replace reserved commands report errors rather than letting registration order select a winner.

Standard families are installed from supplied capabilities. Help and version use application identity/build metadata; configuration and PromptKit providers install their complete corresponding families. Provider registration is lazy and does not acquire configuration or construct engines. Help and version remain available with missing or invalid configuration. Do not install placeholder commands or claim complete adoption for unsupported operations.

Handler Inputs And Invocation State

Handlers receive typed input structs with explicit flag and operand bindings. Use presence-aware fields where omission matters; preserve explicitly supplied empty, false, and zero values independently of parser defaults. Context, streams, and execution dependencies are separate from CLI inputs.

Create fresh input and backend command/flag state per invocation. Registered commands must not retain input values, collections, or presence state across runs. This does not establish a concurrent-dispatch guarantee.

Applications may interpret parsed domain values and provide domain value parsers through the binding system. Raw-argument parsing is not the primary handler model. Keep input declarations available without application initialization.

Public Facade And Dependency Direction

ADR 0003 records the root commandkit facade and internal adapter boundary. The root is the sole initial supported public package and defines CommandKit's public named types. Additional public packages require a deliberate decision based on a durable consumer responsibility.

Public handles retain private implementation state and expose explicitly selected methods. Use explicit forwarding and conversions that preserve type identity, value ownership, callback lifetime, presence, and public error semantics. Do not alias or anonymously embed implementation types into the public API, promote internal methods, or expose backend bridge methods.

Implementation belongs under Go's internal/ boundary. Dependencies run from the facade inward; internal production packages do not import the root. Shared implementation contracts belong inside the internal boundary. Public signatures, fields, callbacks, constraints, and method sets must not expose internal or Cobra/pflag types. Backend objects must not escape through loosely typed values or returned errors.

Standard contracts such as context.Context and io.Writer remain appropriate. Other public dependency types require deliberate API selection. Application-owned input types remain application-owned. Do not expand exports merely to simplify internal assembly.

Backend And Library Integration

ADR 0002 selects Cobra with pflag as the sole initial backend. Their types and operations stay inside an internal adapter that translates CommandKit-owned definitions into backend machinery. Registry logic, standard handlers, and shared internal representations remain independent of backend-specific structures.

Reuse backend routing and parsing mechanisms, adapting them to selected CommandKit semantics. Do not replicate Cobra's entire API through renamed wrappers. Introduce narrow internal interfaces where actual interactions justify them; a public backend selection or plugin framework is not part of the design.

ConfigKit and PromptKit own configuration composition, provenance, inspection semantics, secret classification, and native rendering. Applications provide schemas, acquisition, domain resolution and validation, and construction of inspection providers. CommandKit exposes those capabilities without implementing a parallel configuration or prompt engine. Use independently released public contracts; do not import sibling internal packages or depend on adjacent checkouts.

Scope And Non-goals

Keep packages and abstractions proportionate to cohesive responsibilities. The library is not a general application runtime, dependency-injection framework, logging system, hosted service, or standalone application. It does not prescribe domain execution vocabulary outside the standard suite.

The CLI roadmap 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 changes under the release policy.

Base restrictions and guarantees on selected requirements. Configuration and prompt libraries retain their own confidentiality contracts; standard output must use their safe inspection APIs without promising that arbitrary application content is safe for public disclosure. New threat scope or restrictions require a deliberate decision under the agent policy.