Accept the captured declaration architecture and align documentation

This commit is contained in:
2026-10-10 16:19:45 +00:00
parent 8f86852456
commit 160604095c
10 changed files with 325 additions and 57 deletions

View File

@@ -2,7 +2,7 @@
**Base Policy Version:** 1.3
**Last Updated**: 2026-10-08
**Last Updated**: 2026-10-10
**Upstream Source:** [architecture.md](https://gitea.maximumdirect.net/eric/policy/src/commit/d84a38ebab26f048cafbe59a2246700c35d29843/docs/policy/architecture.md)
@@ -44,14 +44,22 @@ flexibility to express genuine application requirements within one command model
[ADR 0001](../adr/0001-command-dispatch-and-inputs.md) records the selected
CommandKit-owned dispatcher, per-instance registry, and typed-input model.
[ADR 0011](../adr/0011-captured-declarations-and-installation.md) refines declaration
capture, installation, optional-family ownership, and invocation input lifetimes.
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.
Namespaces provide the ownership boundary. Core construction reserves help and
version. Optional standard families, including config and promptkit, own their
root namespace when installed; importing an integration or declaring an absent
family claims no namespace. An application may occupy an uninstalled family name.
Installing the standard family then reports a collision, as does application
registration after the standard family is installed. Neither order merges groups
or replaces handlers. Installed standard families cannot acquire private
application operations beneath them. Standard-family declarations are root-only;
nesting a real family beneath another group reports an assembly error.
Applications own their executable entry points, context creation, signals,
stream selection, runtime construction, and final process exit. CommandKit
@@ -71,9 +79,24 @@ retain control of their own output. [ADR 0005](../adr/0005-invocation-outcomes.m
describes the outcome and delivery model.
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.
package-global or import-time registries. Applications and integrations supply
the same captured command declarations through the core installation API.
Declaration factories capture metadata, bindings, and callback references eagerly;
construction errors remain attached for installation to report. Capture the
metadata collections needed to keep later edits to a source declaration from
changing a returned command. Application callback objects retain their ownership.
One definition supplies routing, parsing, and help metadata.
Validate each installation batch before mutating the instance registry. A failed
construction yields no usable application; a failed later registration leaves the
existing registry intact. Separate successful registration calls are not one
transaction. Duplicate paths and attempts to replace reserved commands report
errors rather than letting registration order select a winner.
Explicit absent-command declarations contribute no commands, help entries, or
namespace claims; attached errors are reported before skipping absence. An invalid
zero declaration is not absence. Integrations define their own empty-suite
semantics and retain invalid wiring errors even when capabilities are narrowed.
Standard families are assembled from declared provider capabilities. Each family
specifies its own resources and supported operations; shared verbs retain
@@ -100,7 +123,31 @@ application-owned.
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.
and execution dependencies are separate from CLI inputs. Integration suites keep
their typed CLI input separate from shared acquisition state. For a configuration
operation, initialize and populate each selected scope's input independently,
applying only its applicable selector bindings; initialize shared state once for
the selected inspection invocation. Named definition inspection uses one input
and one shared state. Complete applicable preflight and input checks before shared
state initialization and provider acquisition. Factories need not run after a
failure and remain uninvoked during construction, installation, help, version,
and scope discovery.
Omitted input and state factories supply the respective type's zero value,
including nil for pointers. Caller factories and callbacks retain responsibility
for objects they return or reference; do not promise arbitrary deep copies,
repair caller-created aliases, or silently allocate arbitrary pointer types.
Core-owned parsed collections stay independent where values are applied to
separate inputs.
Provide typed binding composition through supported public core contracts when
integrations need to apply captured converted values to selected inputs. Preserve
binding identity and presence without exposing private setters or backend state.
Required-value checks apply to the selected binding subset. Missing required
operator input is a usage failure; invalid binding selection or destination is a
wiring failure with operational classification when detected during invocation.
Metadata defects detectable during assembly remain installation errors. Input
composition does not create a second parser or a raw-argument handler model.
CommandKit keeps parsed values, collections, and presence from one invocation out
of subsequent runs. Storage allocation and safe reuse are implementation choices;
@@ -114,10 +161,20 @@ 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.
[ADR 0010](../adr/0010-optional-integration-modules.md) scopes the root
`commandkit` facade to the core module and selects separate optional integration
modules with their own public package contracts. It partially supersedes
[ADR 0003](../adr/0003-public-facade.md), whose remaining facade and internal
adapter principles apply to the core and integrations alike.
The core owns command declarations, registration, bindings, dispatch, help/version,
shared syntax, diagnostics, and outcomes. Each integration owns its standard
handlers, provider contracts, reports, adapters, and integration-specific public
types. Dependencies point from integrations toward the core; an integration may
depend on another integration when its responsibility requires that relationship.
Document those dependencies. Core public signatures, implementation imports, and
module requirements remain independent of optional integration libraries,
including dependencies introduced through tests, examples, or tools.
Public handles retain private implementation state and expose explicitly selected
methods. Any forwarding and conversions must preserve type identity, value
@@ -125,9 +182,9 @@ ownership, callback lifetime, presence, and supported public error semantics. Do
not alias public types to internal or backend types, anonymously embed those types
to promote methods, or expose implementation bridge methods.
Straightforward implementation may live in the root package without expanding
its exports. Introduce internal packages, interfaces, and conversions where they
simplify implementation or protect the backend boundary. Package organization and
Straightforward implementation may live in an owning public package without
expanding its exports. Introduce internal packages, interfaces, and conversions
where they simplify implementation or protect the backend boundary. Package organization and
the amount of internal layering follow implementation needs.
Public signatures, fields, callbacks, constraints, and method sets must not expose
@@ -138,9 +195,13 @@ retain their documented handling; this boundary does not require inspecting or
transforming arbitrary application objects.
Standard contracts such as `context.Context` and `io.Writer` remain appropriate.
Public types from integration libraries, such as ConfigKit and PromptKit, may be
selected as deliberate dependencies. Application-owned input types remain
application-owned. Do not expand exports merely to simplify internal assembly.
Upstream public types may be selected as deliberate dependencies in the
integrations that own them; that permission does not justify optional library
dependencies in the core. Core diagnostics use a CommandKit-owned severity type,
and integrations convert upstream diagnostics while preserving selected outcome
and error semantics. Application-owned input types remain application-owned.
Expose narrow core composition contracts for demonstrated integration needs,
without exporting private assembly or backend structures.
## Backend And Library Integration