Refine backend composition and input lifecycle decisions
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# Registration and execution internals
|
||||
|
||||
Status: proposed internal design for the finalized consumer API; no implementation
|
||||
has begun. Two public composition seams identified below need resolution before
|
||||
the staged implementation plan is finalized.
|
||||
has begun. Runnable-command children and scope-error attachment are selected API
|
||||
additions to incorporate into the registration API document. OQ-1 remains open
|
||||
for later discussion before the staged implementation plan is finalized.
|
||||
|
||||
## Purpose and authority
|
||||
|
||||
@@ -163,6 +164,14 @@ Keep payload and children independent in the private model. Do not introduce a
|
||||
new prohibition on runnable commands with children merely because separate leaf
|
||||
and group constructors are convenient.
|
||||
|
||||
The selected public addition is `Children []Command` on `CommandSpec[I]`. The
|
||||
registration API currently has no way to combine a handler with children; the
|
||||
private model alone cannot expose the behavior described by
|
||||
[ADR 0006](../adr/0006-command-grammar.md). Capture the child-handle slice using the
|
||||
same ownership and immediate composition checks as `Group`, and enforce the same
|
||||
placement rules at installation. `Group` remains a convenience for non-runnable
|
||||
parents. This addition requires no separate registration mechanism.
|
||||
|
||||
### Divide validation by responsibility and lifetime
|
||||
|
||||
Use one implementation of each core metadata rule:
|
||||
@@ -211,6 +220,11 @@ template, initialize suite input, or invoke a parser a second time.
|
||||
`FlagValues.ApplyTo` selects the original identities and applies their prepared
|
||||
values to the supplied destination.
|
||||
|
||||
All supplied occurrences undergo conversion, including selectors inapplicable to
|
||||
the selected scope and values supplied alongside help. Scope filtering governs
|
||||
value application and required-value checks, not conversion. An earlier malformed
|
||||
singleton occurrence remains an error even if a later occurrence is valid.
|
||||
|
||||
Recommend a private identity token per original binding and an invocation-local
|
||||
lookup from token to prepared entry. Handle copies preserve identity; lookalike
|
||||
bindings get a different token. A private nonzero-sized token object avoids
|
||||
@@ -231,8 +245,11 @@ usage outcomes. An integration may wrap those causes with scope/family context
|
||||
without parsing error messages or inventing another outcome protocol.
|
||||
|
||||
Help still converts supplied occurrences and rejects malformed values through the
|
||||
same preparation logic, but does not materialize command/suite input or enforce
|
||||
execution-required fields. Presence, singleton repetition, and repeated-value
|
||||
same preparation logic, but does not materialize the target command's application
|
||||
or suite input, invoke its validation or execution callbacks, or enforce its
|
||||
execution-required fields. Suite state factories and providers also remain
|
||||
uninvoked. The built-in help command may prepare its own private typed input
|
||||
through the common compiler. Presence, singleton repetition, and repeated-value
|
||||
semantics remain those of the finalized API and selected grammar.
|
||||
|
||||
## One compiled execution path, including help
|
||||
@@ -350,7 +367,7 @@ configuration views with their proper owners.
|
||||
`ConfigScope` constructs a public `ckconfig.Scope` and delegates configuration
|
||||
command generation to `ckconfig`. It must not construct another config family or
|
||||
reach into `ckconfig`'s private prepared suite. Its construction-error handoff is
|
||||
the second unresolved seam below.
|
||||
the selected `ckconfig.WithScopeError` operation described below.
|
||||
|
||||
### Share mechanics where ownership supports them
|
||||
|
||||
@@ -391,21 +408,58 @@ three command sources: built-ins, application declarations, and integrations.
|
||||
Include invalid bindings, conflicting roots in either order, an invalid final
|
||||
member of a batch, nested root-only declarations, absence with retained errors,
|
||||
source metadata edits after capture, and declaration reuse across apps.
|
||||
Include runnable parents with children through `CommandSpec.Children`, applying
|
||||
the same capture, collision, and placement checks as ordinary groups.
|
||||
|
||||
For execution, check wrapped wiring versus input failures, fresh repeatable
|
||||
collections, pointer-shaped scope inputs with shared state, scope-aware validation,
|
||||
help without factories/providers, and metadata refresh without callback replay.
|
||||
help without target application/suite factories or providers, and metadata refresh
|
||||
without callback replay. Check that supplied but inapplicable selectors still
|
||||
undergo conversion, including on help paths, while the built-in help command can
|
||||
prepare its own private input through the common compiler.
|
||||
Evidence for the internal path itself can inspect the shared installer/compiler;
|
||||
do not turn a private function name or exact allocation count into a public
|
||||
contract. These are review targets for the future implementation, not a request
|
||||
to add or run tests during this planning pass.
|
||||
|
||||
## Resolved scope-error handoff (OQ-2)
|
||||
|
||||
The selected `Scope[I, S]` includes private adapter-construction issues owned by
|
||||
`ckconfig`. Before the selected addition below, `ckprompt.ConfigScope` could not
|
||||
attach its original nil-loader error through supported public contracts. An
|
||||
`Acquire == nil` check alone is insufficient: narrowing `Operations` to empty makes a scope
|
||||
metadata-only, while the original invalid loader must remain an error. Wrapping
|
||||
the nil loader in a non-nil acquisition closure would incorrectly defer it to
|
||||
invocation. A core `WithError` only accepts a `Command`, not a scope.
|
||||
|
||||
**Selected:** add the integration-owned operation
|
||||
`ckconfig.WithScopeError[I, S](scope Scope[I, S], err error) Scope[I, S]`.
|
||||
It returns a scope retaining the original issue, preserving supported error
|
||||
identity. Repeated attachments preserve earlier causes and leave the original
|
||||
scope unchanged; a nil error preserves the scope. Retained causes survive scope
|
||||
copies and narrowing of `Operations`. The family factory collects those issues
|
||||
into its command declaration before capability selection or absence can discard
|
||||
them. `ConfigScope` uses this for its original loader validation and
|
||||
otherwise fills the ordinary public scope fields.
|
||||
|
||||
This mirrors the accepted core retained-error model at the boundary that needs
|
||||
it. It does not add scope installation, expose private representations, or move
|
||||
PromptKit types into the core. Scope capture still occurs at the existing family
|
||||
factory; this operation is evidence attachment rather than a new lifecycle.
|
||||
|
||||
**Alternative considered:** give the public scope declaration an explicit
|
||||
construction-error field, consumed by the family factory alongside provider metadata. This is simple
|
||||
and permits application-created adapters to supply errors directly. It expands
|
||||
mutable public representation and requires defining preservation/combination of
|
||||
multiple errors; the opaque attachment operation keeps those details private.
|
||||
|
||||
## Open Questions
|
||||
|
||||
The main internal design can use the existing finalized API. The following two
|
||||
seams need an explicit API clarification or small approved extension. Do not
|
||||
resolve them with private-module imports, dummy providers, reflection, or hidden
|
||||
global state.
|
||||
OQ-1 remains unresolved; its recommendation and alternatives below are retained
|
||||
for later discussion. The selected API additions above need to be reflected in
|
||||
the registration API document before implementation planning is finalized. Do not
|
||||
resolve the remaining question with private-module imports, dummy providers,
|
||||
reflection, or hidden global state.
|
||||
|
||||
### OQ-1: Retaining core binding errors when a family is absent
|
||||
|
||||
@@ -448,35 +502,3 @@ This needs no new API and is proportionate to installed behavior, but limits the
|
||||
meaning of suite validation before absence to integration metadata and retained
|
||||
adapter issues rather than all unused bindings. Choose it deliberately,
|
||||
rather than silently making empty capabilities swallow invalid declarations.
|
||||
|
||||
### OQ-2: Retaining errors in a scope constructed by another integration
|
||||
|
||||
The selected `Scope[I, S]` includes private adapter-construction issues owned by
|
||||
`ckconfig`. `ckprompt.ConfigScope` returns that scope type, but cannot attach its
|
||||
original nil-loader error through supported public contracts. An `Acquire == nil`
|
||||
check alone is insufficient: narrowing `Operations` to empty makes a scope
|
||||
metadata-only, while the original invalid loader must remain an error. Wrapping
|
||||
the nil loader in a non-nil acquisition closure would incorrectly defer it to
|
||||
invocation. A core `WithError` only accepts a `Command`, not a scope.
|
||||
|
||||
**Recommendation:** approve an integration-owned operation, schematically
|
||||
`ckconfig.WithScopeError[I, S](scope Scope[I, S], err error) Scope[I, S]`.
|
||||
It returns a scope retaining the original issue, preserving supported error
|
||||
identity; a nil error preserves the scope. The family factory collects those
|
||||
issues into its command declaration before capability selection or absence can
|
||||
discard them. `ConfigScope` uses this for its original loader validation and
|
||||
otherwise fills the ordinary public scope fields.
|
||||
|
||||
This mirrors the accepted core retained-error model at the boundary that needs
|
||||
it. It does not add scope installation, expose private representations, or move
|
||||
PromptKit types into the core. Scope capture still occurs at the existing family
|
||||
factory; this operation is evidence attachment rather than a new lifecycle.
|
||||
|
||||
**Alternative:** give the public scope declaration an explicit construction-error
|
||||
field, consumed by the family factory alongside provider metadata. This is simple
|
||||
and permits application-created adapters to supply errors directly. It expands
|
||||
mutable public representation and requires defining preservation/combination of
|
||||
multiple errors; the opaque attachment operation keeps those details private.
|
||||
|
||||
Neither seam requires a general plugin system. Confirm their resolutions before
|
||||
turning this design and the module roadmap into ordered implementation stages.
|
||||
|
||||
Reference in New Issue
Block a user