Files
commandkit/docs/policy/architecture.md

166 lines
8.8 KiB
Markdown
Raw Normal View History

# Architecture Policy
**Base Policy Version:** 1.3
**Last Updated**: 2026-10-06
**Upstream Source:** [architecture.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/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](../development.md#task-specific-reading-guide) 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](release.md).
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](../adr/0001-command-dispatch-and-inputs.md) 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. CommandKit reports registration errors
for attempts to 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 assembled from declared provider capabilities. Each family
specifies its own resources and supported operations; shared verbs retain
consistent meanings across families. Configuration scopes describe their supported
inspection operations. CommandKit installs the supplied handlers and metadata and
reports actual availability through help and discovery. Missing upstream
capabilities leave other supported operations available.
Help and version use identity/build metadata. CommandKit's registration and
metadata paths leave acquisition callbacks uninvoked. Help and version remain
available with missing or invalid configuration. Callers retain their startup and
callback effects. Version reporting defaults to application identity; explicit
component selection reports embedded library identity.
These rules govern CommandKit's own API, dispatcher, and standard handlers.
Provider contracts define required inputs and results for enabled operations;
callback internals and application execution remain consumer choices. Shared
inspection/execution loading and focused acquisition callbacks are recommended
integration practices. Independent consumer use of other CLI frameworks remains
application-owned.
## 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.
CommandKit creates fresh input and backend command/flag state per invocation,
keeping its parsed values, collections, and presence out of subsequent runs.
Caller-owned closures and runtime state retain their own lifecycle. Concurrent
dispatch is a separate contract.
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](../adr/0003-public-facade.md) 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](../adr/0002-cobra-backend.md) 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](../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
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](agents.md).