Files
commandkit/docs/adr/0001-command-dispatch-and-inputs.md

79 lines
3.8 KiB
Markdown
Raw Permalink Normal View History

# ADR 0001: Own dispatch through captured declarations and typed inputs
## Status
Accepted.
## Date
2026-11-07; consolidates decisions made on 2026-10-06 and 2026-10-10.
## Context
Applications repeat routing, flag parsing, help, and inspection commands while
also needing their own domain commands. Sharing only isolated command handlers
would leave much of that infrastructure and its inconsistent behavior with each
application. Optional integrations also need to assemble commands through the
same public mechanisms as applications.
## Decision
CommandKit owns dispatch, shared parsing, presence tracking, help, syntax
failures, and standard command mechanics. Applications own their domain commands,
validation, effects, runtime construction, and executable lifecycle. CommandKit
accepts caller context and streams and returns outcomes rather than terminating
the process.
Use an explicitly constructed, per-instance registry. Applications and
integrations supply captured declarations containing routing, parsing, help
metadata, and callback references. One declaration supplies those views of the
command. Captured metadata is insulated from later edits to its source;
application objects referenced by callbacks remain caller-owned.
Declarations share one installation boundary. Construction issues are retained
for installation, and each installation batch is validated before registry
mutation. Collisions are errors rather than order-dependent replacement.
Optional standard families claim their namespaces when installed, not when
imported. Their canonical operations remain integration-owned; application
commands live outside installed standard families.
Handlers receive typed inputs through explicit flag and operand bindings.
Presence is separate from value so omission differs from supplied empty, false,
or zero values. Domain parsers and validation remain application-owned. Core
provides typed composition for integrations without exposing parser state or
requiring a second argument parser.
Parsed state is independent between invocations. Integration inputs for selected
scopes or comparison sides are distinct from invocation-wide acquisition state.
Applications own the objects and caches returned by their factories. CommandKit
coordinates its own preparation and calls without promising arbitrary deep copies
or concurrent dispatch.
Construction, installation, help, version, and capability discovery use metadata
without acquiring application state. The selected operation acquires what it
needs after applicable input checks. Caller startup and callback effects retain
their own lifecycle.
## Alternatives considered
- Application dispatchers forwarding standard families would share handlers but
leave custom-command parsing, root help, and diagnostics duplicated.
- Raw-argument handlers or string-keyed input access would leave typed input
assembly and presence handling with every consumer.
- Reflection, struct tags, or generated bindings could shorten declarations but
add another declaration language or toolchain.
- Import-time registries or a separate integration registration framework would
introduce hidden state or parallel assembly conventions.
## Consequences
Applications use one command system while retaining domain ownership. Explicit
bindings and captured declarations require deliberate assembly, but integrations
can supply complete families through the same public contracts.
[GoDoc](../../command.go) owns declaration, installation, and callback contracts;
the [consumer guide](../consumers/guide.md) explains their use. Exact grammar,
commands, and outcomes belong in the [CLI reference](../cli.md). Binding identity,
absence handling, factory defaults, and operation-specific preparation timing
can evolve within this architecture through deliberate API changes.