Resolve unused binding validation for empty integration suites
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
Status: proposed internal design for the finalized consumer API; no implementation
|
||||
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.
|
||||
additions to incorporate into the registration API document. Both composition
|
||||
questions below are resolved; the staged implementation plan remains to be written.
|
||||
|
||||
## Purpose and authority
|
||||
|
||||
@@ -192,8 +192,10 @@ do not add a global intern table, reflection-driven compiler, or mutable
|
||||
|
||||
Core name/short-name/help-reservation rules also check the combined standard and
|
||||
selector flags on generated commands. Integration code should not reproduce
|
||||
those rules with handwritten reserved-name lists. Error checking for selectors
|
||||
in an absent definition family is the unresolved seam described below.
|
||||
those rules with handwritten reserved-name lists. Validate bindings used by
|
||||
generated commands; unused selector bindings in an absent family are ignored,
|
||||
as clarified in the OQ-1 resolution below. Retained adapter-construction errors
|
||||
still reach installation.
|
||||
|
||||
## One typed conversion and application mechanism
|
||||
|
||||
@@ -453,52 +455,45 @@ 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
|
||||
## Resolved unused-binding validation (OQ-1)
|
||||
|
||||
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.
|
||||
**Selected:** empty definition suites contribute no commands, and unused selector
|
||||
bindings are ignored. Generate commands for the supplied capabilities and validate
|
||||
the bindings needed by those commands. When neither definition-inspection
|
||||
capability is enabled, the family contributes no namespace, help entry, or handler.
|
||||
There is no need to construct validation-only commands or a temporary application
|
||||
for selector bindings that will not be installed.
|
||||
|
||||
### OQ-1: Retaining core binding errors when a family is absent
|
||||
This follows the capability-driven assembly model: selecting no capabilities
|
||||
naturally produces no commands. Rejecting unused bindings would report defects
|
||||
that cannot affect routing, parsing, or execution. This clarifies the validation
|
||||
boundary while preserving ADR 0011's selected empty-suite behavior; it does not
|
||||
promise exhaustive validation of unused metadata.
|
||||
|
||||
The API says suite validation precedes absence and invalid wiring must not be
|
||||
swallowed. It does not explicitly define the validation boundary for selector
|
||||
bindings when both definition capabilities are absent. If those bindings must
|
||||
still be validated, `ckprompt` can retain its own adapter errors, but `Flag`
|
||||
validation state is private to the core. An integration can construct a temporary
|
||||
command containing its selector bindings, yet the finalized API offers no way to
|
||||
transfer that
|
||||
command's retained errors to `NoCommand()`. Discarding it loses evidence;
|
||||
installing it adds a command that should be absent. Validating through a temporary
|
||||
`App` would work mechanically but construct built-ins, routing ownership, and a
|
||||
registry merely to inspect metadata.
|
||||
An explicitly invalid adapter construction remains distinct from an omitted
|
||||
capability. Retain errors such as a nil loader supplied to an adapter even when
|
||||
its capabilities are subsequently cleared. Return ordinary `NoCommand()` for an
|
||||
empty definition suite, attaching any retained construction errors through the
|
||||
existing `WithError`. Installation checks those errors before skipping absence.
|
||||
No validation-bearing `NoCommand` overload or public declaration-validation helper
|
||||
is needed.
|
||||
|
||||
**Recommendation:** approve a narrow extension of the existing absence factory,
|
||||
schematically `NoCommand(validation ...Command) Command`. A no-op can retain
|
||||
local construction/structural errors from eagerly captured validation declarations
|
||||
without installing their commands or claiming their namespaces. The empty
|
||||
definition factory builds a metadata-only validation declaration using the same
|
||||
generated flag assembly, then returns absence carrying that evidence.
|
||||
The binding rule also applies to configuration selectors unused by any generated
|
||||
inspection command. Existing configuration-suite semantics remain unchanged:
|
||||
zero named scopes is an error, while named metadata-only scopes supply the real
|
||||
`config scopes` discovery command and remain valid. Integration scope identifiers,
|
||||
applicability references, and enabled-provider wiring retain their own validation;
|
||||
ignoring unused bindings does not erase retained adapter errors or bypass checks
|
||||
on commands that are generated.
|
||||
|
||||
This reuses the common declaration validator and keeps one installation-time
|
||||
error boundary. Validation sources are captured data, not preparation callbacks;
|
||||
they do not acquire providers or introduce registry collision checks for roots
|
||||
that will not be installed. Specify the evidence-only behavior explicitly before
|
||||
changing the API. Plain `NoCommand()` retains its current meaning.
|
||||
This construction-time rule does not skip invocation-time conversion of a supplied
|
||||
flag on an installed command merely because it is inapplicable to the selected
|
||||
scope. Conversion and scope-specific application remain separate as described
|
||||
above.
|
||||
|
||||
**Alternative:** add a core declaration-validation function returning `error` for
|
||||
local metadata/structure, and attach its result through the existing `WithError`.
|
||||
That also avoids a temporary app and duplicated flag policy. It adds a public
|
||||
validation entry point and a second observation point for errors; ensure it uses
|
||||
the same validator rather than evolving independent rules. It is viable if
|
||||
explicit validation is useful beyond absent families.
|
||||
|
||||
**Alternative requiring a contract clarification:** validate only the bindings of
|
||||
actual generated commands. An absent family has no installed bindings, so unused
|
||||
selectors would not undergo core validation; retained adapter errors still fail.
|
||||
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.
|
||||
**Alternatives considered:** rejecting empty definition suites could catch an
|
||||
accidental omission, but would make an empty capability selection an error without
|
||||
a demonstrated need. Validating all unused bindings, through either an extended
|
||||
absence factory or an explicit validation helper, would catch latent defects but
|
||||
add public API and validation machinery for commands that do not exist. Neither
|
||||
alternative is selected.
|
||||
|
||||
Reference in New Issue
Block a user