Refine registration alternatives and list remaining decisions
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
# Registration API alternatives
|
# Registration API alternatives
|
||||||
|
|
||||||
Status: design mockup for discussion; neither alternative is implemented or
|
Status: design mockup for discussion; none of the alternatives is implemented or
|
||||||
selected by this document.
|
selected by this document.
|
||||||
|
|
||||||
## Purpose and authority
|
## Purpose and authority
|
||||||
@@ -26,7 +26,7 @@ proposed here; deferred capabilities remain deferred.
|
|||||||
|
|
||||||
## Common requirements
|
## Common requirements
|
||||||
|
|
||||||
Both alternatives must provide:
|
All alternatives must provide:
|
||||||
|
|
||||||
- A core-only consumer importing neither integration nor its upstream library.
|
- A core-only consumer importing neither integration nor its upstream library.
|
||||||
- Integration-supplied standard commands and adapters; applications supply
|
- Integration-supplied standard commands and adapters; applications supply
|
||||||
@@ -70,22 +70,35 @@ The illustrative adapter signatures are:
|
|||||||
func FromConfigKit[C, T any](
|
func FromConfigKit[C, T any](
|
||||||
name, summary string,
|
name, summary string,
|
||||||
load func(context.Context, Selection, C) (*configkit.Result[T], error),
|
load func(context.Context, Selection, C) (*configkit.Result[T], error),
|
||||||
) (Scope[C], error)
|
) Scope[C]
|
||||||
|
|
||||||
// In ckprompt:
|
// In ckprompt:
|
||||||
func ConfigScope[C any](
|
func ConfigScope[C any](
|
||||||
load func(context.Context, ckconfig.Selection, C) (*promptkit.Engine, error),
|
load func(context.Context, ckconfig.Selection, C) (*promptkit.Engine, error),
|
||||||
) (ckconfig.Scope[C], error)
|
) ckconfig.Scope[C]
|
||||||
|
|
||||||
func FromEngine[C any](
|
func FromEngine[C any](
|
||||||
load func(context.Context, ckconfig.Selection, C) (*promptkit.Engine, error),
|
load func(context.Context, ckconfig.Selection, C) (*promptkit.Engine, error),
|
||||||
) (Suite[C], error)
|
) Suite[C]
|
||||||
```
|
```
|
||||||
|
|
||||||
Using `ckconfig.Selection` for the PromptKit adapters describes their existing
|
Using `ckconfig.Selection` for the PromptKit adapters describes their existing
|
||||||
configuration-selection inputs. It does not move that integration-specific type
|
configuration-selection inputs. It does not move that integration-specific type
|
||||||
back into the core. `ckprompt` already has the selected dependency on `ckconfig`.
|
back into the core. `ckprompt` already has the selected dependency on `ckconfig`.
|
||||||
|
|
||||||
|
These adapters construct declarations without acquiring providers or returning
|
||||||
|
errors. Option A validates the complete suite in `Register`; Option B validates
|
||||||
|
it in the complete-group factory; Option C validates it during core installation.
|
||||||
|
All validate before registry mutation. Invalid wiring, including a nil loader,
|
||||||
|
must remain detectable in the declaration rather than becoming an invocation-time
|
||||||
|
failure inside an otherwise non-nil wrapper. Invalid configuration returned by a
|
||||||
|
valid loader remains an invocation-time failure.
|
||||||
|
|
||||||
|
This consolidates declaration errors at a useful assembly boundary. It does not
|
||||||
|
require every future constructor to be infallible: constructors that perform
|
||||||
|
genuinely fallible work may still return errors. The existing adapter constructors
|
||||||
|
only reject nil loaders at construction, so they do not demonstrate that need.
|
||||||
|
|
||||||
Adapters supply appropriate supported operations. Provider declarations can also
|
Adapters supply appropriate supported operations. Provider declarations can also
|
||||||
describe supported subsets through typed callbacks, so callers need not enable
|
describe supported subsets through typed callbacks, so callers need not enable
|
||||||
every available inspection operation. Advanced composition does not require
|
every available inspection operation. Advanced composition does not require
|
||||||
@@ -98,38 +111,29 @@ without forcing PromptKit definition providers to use a configuration-specific
|
|||||||
selector wrapper. The exact selector constructors are a separate part of the
|
selector wrapper. The exact selector constructors are a separate part of the
|
||||||
typed-input design, not a reason to add a registration framework.
|
typed-input design, not a reason to add a registration framework.
|
||||||
|
|
||||||
For the composed sketches below, `makeInspectionSuites` represents this wiring:
|
### Consumer assumptions
|
||||||
|
|
||||||
```go
|
The simple ConfigKit examples have no domain selectors, overrides, or application
|
||||||
appScope, err := ckconfig.FromConfigKit(
|
state. Under the current generic sketch, their loader accepts an unused
|
||||||
"app", "Application settings.", loadAppConfig,
|
`struct{}` context argument and their suite uses `struct{}` with no `NewContext`
|
||||||
)
|
callback. This makes the remaining type plumbing visible rather than hiding it
|
||||||
if err != nil {
|
behind an `AppInput` type or helper. Whether to offer a context-free loader form
|
||||||
return err
|
is still open; these examples do not settle that API.
|
||||||
}
|
|
||||||
engineScope, err := ckprompt.ConfigScope(loadEngine)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
configSuite := ckconfig.Suite[*RunState]{
|
|
||||||
NewContext: newRunState,
|
|
||||||
Scopes: []ckconfig.Scope[*RunState]{appScope, engineScope},
|
|
||||||
}
|
|
||||||
definitions, err := ckprompt.FromEngine(loadEngine)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
definitions.NewContext = newRunState
|
|
||||||
```
|
|
||||||
|
|
||||||
Here the loaders accept `*RunState`. The illustrative `newRunState` callback is
|
In the composed examples, both loaders accept `*RunState` and all provider and
|
||||||
|
suite assembly is shown inline. The illustrative `newRunState` callback is
|
||||||
invoked by the selected handler, not during assembly. Application state can hold
|
invoked by the selected handler, not during assembly. Application state can hold
|
||||||
an invocation-local cache shared by the selected configuration scopes. Separate
|
an invocation-local cache shared by the selected configuration scopes. Separate
|
||||||
families do not acquire state together merely because both are registered.
|
families do not acquire state together merely because both are registered.
|
||||||
Keeping `engineScope` while omitting definition registration enables only
|
Keeping the engine scope while omitting definition registration enables only
|
||||||
PromptKit configuration inspection; keeping definitions while omitting that
|
PromptKit configuration inspection; keeping definitions while omitting that
|
||||||
scope enables only definition inspection. Importing `ckprompt` enables neither.
|
scope enables only definition inspection. Importing `ckprompt` enables neither.
|
||||||
|
|
||||||
|
`greet` and `sessionGroup` represent already constructed application-owned
|
||||||
|
commands, whose construction is identical across the alternatives. Their domain
|
||||||
|
implementation and the loaders' bodies are omitted; no integration assembly or
|
||||||
|
error handling is hidden in a `makeInspectionSuites` helper.
|
||||||
|
|
||||||
## Option A: integration convenience functions install complete groups
|
## Option A: integration convenience functions install complete groups
|
||||||
|
|
||||||
### Proposed public shape
|
### Proposed public shape
|
||||||
@@ -169,18 +173,14 @@ provided by construction; there is no inspection-provider setup.
|
|||||||
### ConfigKit-only consumer
|
### ConfigKit-only consumer
|
||||||
|
|
||||||
```go
|
```go
|
||||||
scope, err := ckconfig.FromConfigKit(
|
|
||||||
"app", "Application settings.", loadAppConfig,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
app, err := commandkit.New(identity, greet)
|
app, err := commandkit.New(identity, greet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ckconfig.Register(app, ckconfig.Suite[AppInput]{
|
if err := ckconfig.Register(app, ckconfig.Suite[struct{}]{
|
||||||
Scopes: []ckconfig.Scope[AppInput]{scope},
|
Scopes: []ckconfig.Scope[struct{}]{
|
||||||
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -192,17 +192,21 @@ its loader, with no `ckprompt` or PromptKit dependency.
|
|||||||
### Composed consumer
|
### Composed consumer
|
||||||
|
|
||||||
```go
|
```go
|
||||||
configSuite, definitions, err := makeInspectionSuites()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
app, err := commandkit.New(identity, sessionGroup)
|
app, err := commandkit.New(identity, sessionGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ckconfig.Register(app, configSuite); err != nil {
|
if err := ckconfig.Register(app, ckconfig.Suite[*RunState]{
|
||||||
|
NewContext: newRunState,
|
||||||
|
Scopes: []ckconfig.Scope[*RunState]{
|
||||||
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
|
ckprompt.ConfigScope(loadEngine),
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
definitions := ckprompt.FromEngine(loadEngine)
|
||||||
|
definitions.NewContext = newRunState
|
||||||
if err := ckprompt.Register(app, definitions); err != nil {
|
if err := ckprompt.Register(app, definitions); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -220,7 +224,8 @@ registration independently installs the supplied `promptkit` operations.
|
|||||||
family-builder API solely to support extraction.
|
family-builder API solely to support extraction.
|
||||||
- Works with ordinary core command/group concepts, without a new integration
|
- Works with ordinary core command/group concepts, without a new integration
|
||||||
object, callback protocol, or application-wide options language.
|
object, callback protocol, or application-wide options language.
|
||||||
- Provider validation and installation are coordinated within one call.
|
- Provider validation and installation are coordinated within one call, without
|
||||||
|
separate error checks for the declaration-only adapter constructors.
|
||||||
- Each module can evolve its provider declarations independently.
|
- Each module can evolve its provider declarations independently.
|
||||||
|
|
||||||
### Costs and limits
|
### Costs and limits
|
||||||
@@ -250,6 +255,9 @@ func Command[C any](suite Suite[C]) (commandkit.Command, error)
|
|||||||
the supplied definition-inspection group. The returned core handle has private
|
the supplied definition-inspection group. The returned core handle has private
|
||||||
implementation state. It does not expose child mutation or standard handlers.
|
implementation state. It does not expose child mutation or standard handlers.
|
||||||
Factory validation and group construction leave acquisition callbacks uninvoked.
|
Factory validation and group construction leave acquisition callbacks uninvoked.
|
||||||
|
Adapter declarations use the shared error-free constructors; suite wiring errors
|
||||||
|
are reported by `Command`, while registry collisions and placement errors are
|
||||||
|
reported by `New` or `Register`.
|
||||||
|
|
||||||
### Core-only consumer
|
### Core-only consumer
|
||||||
|
|
||||||
@@ -259,14 +267,10 @@ integration dependency or configuration to core construction.
|
|||||||
### ConfigKit-only consumer
|
### ConfigKit-only consumer
|
||||||
|
|
||||||
```go
|
```go
|
||||||
scope, err := ckconfig.FromConfigKit(
|
configCommand, err := ckconfig.Command(ckconfig.Suite[struct{}]{
|
||||||
"app", "Application settings.", loadAppConfig,
|
Scopes: []ckconfig.Scope[struct{}]{
|
||||||
)
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
if err != nil {
|
},
|
||||||
return err
|
|
||||||
}
|
|
||||||
configCommand, err := ckconfig.Command(ckconfig.Suite[AppInput]{
|
|
||||||
Scopes: []ckconfig.Scope[AppInput]{scope},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -280,14 +284,18 @@ if err != nil {
|
|||||||
### Composed consumer
|
### Composed consumer
|
||||||
|
|
||||||
```go
|
```go
|
||||||
configSuite, definitions, err := makeInspectionSuites()
|
configCommand, err := ckconfig.Command(ckconfig.Suite[*RunState]{
|
||||||
if err != nil {
|
NewContext: newRunState,
|
||||||
return err
|
Scopes: []ckconfig.Scope[*RunState]{
|
||||||
}
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
configCommand, err := ckconfig.Command(configSuite)
|
ckprompt.ConfigScope(loadEngine),
|
||||||
|
},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
definitions := ckprompt.FromEngine(loadEngine)
|
||||||
|
definitions.NewContext = newRunState
|
||||||
promptCommand, err := ckprompt.Command(definitions)
|
promptCommand, err := ckprompt.Command(definitions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -324,18 +332,103 @@ batch. No guarantee extends across separate registration calls.
|
|||||||
The registry must still recognize any selected standard-namespace restrictions
|
The registry must still recognize any selected standard-namespace restrictions
|
||||||
rather than assume every valid command may be installed at any location.
|
rather than assume every valid command may be installed at any location.
|
||||||
|
|
||||||
|
## Option C: complete declarations validated during installation
|
||||||
|
|
||||||
|
### Proposed public shape
|
||||||
|
|
||||||
|
This variant of Option B defers suite validation and fallible group assembly to
|
||||||
|
core construction or registration:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// In the integration packages:
|
||||||
|
func Command[C any](suite Suite[C]) commandkit.Command
|
||||||
|
```
|
||||||
|
|
||||||
|
A returned command is an uninstalled, potentially invalid declaration. `New` or
|
||||||
|
`Register` prepares and validates the complete batch before committing it. The
|
||||||
|
core needs a supported mechanism for integration-owned validation and assembly
|
||||||
|
without importing integration types or exposing backend machinery. Its exact
|
||||||
|
shape remains open; the shorter consumer syntax does not make that work disappear.
|
||||||
|
|
||||||
|
Preparation uses only declarations and metadata. It does not acquire providers
|
||||||
|
or call application context factories. Installation errors include both invalid
|
||||||
|
suite wiring and registry conflicts. For `New`, a failure yields no usable app;
|
||||||
|
for `Register`, it leaves the prior registry intact.
|
||||||
|
|
||||||
|
### Core-only consumer
|
||||||
|
|
||||||
|
The core-only sketch from Option A remains available. Option C does not require
|
||||||
|
changing every domain command constructor to defer its own validation.
|
||||||
|
|
||||||
|
### ConfigKit-only consumer
|
||||||
|
|
||||||
|
```go
|
||||||
|
app, err := commandkit.New(identity,
|
||||||
|
greet,
|
||||||
|
ckconfig.Command(ckconfig.Suite[struct{}]{
|
||||||
|
Scopes: []ckconfig.Scope[struct{}]{
|
||||||
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Composed consumer
|
||||||
|
|
||||||
|
```go
|
||||||
|
definitions := ckprompt.FromEngine(loadEngine)
|
||||||
|
definitions.NewContext = newRunState
|
||||||
|
app, err := commandkit.New(identity,
|
||||||
|
ckconfig.Command(ckconfig.Suite[*RunState]{
|
||||||
|
NewContext: newRunState,
|
||||||
|
Scopes: []ckconfig.Scope[*RunState]{
|
||||||
|
ckconfig.FromConfigKit("app", "Application settings.", loadAppConfig),
|
||||||
|
ckprompt.ConfigScope(loadEngine),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
ckprompt.Command(definitions),
|
||||||
|
sessionGroup,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
An existing app can instead receive these declarations in one `Register` call.
|
||||||
|
No guarantee extends across separate calls.
|
||||||
|
|
||||||
|
### Advantages
|
||||||
|
|
||||||
|
- Retains Option B's collection and batch-composition capabilities.
|
||||||
|
- Removes intermediate command handles and complete-group factory error checks.
|
||||||
|
- Reports invalid wiring and installation conflicts at one installation boundary.
|
||||||
|
|
||||||
|
### Costs and limits
|
||||||
|
|
||||||
|
- A command handle no longer implies that its integration declaration has passed
|
||||||
|
validation; consumers must install it to obtain that result.
|
||||||
|
- The core must support deferred integration validation and assembly while
|
||||||
|
retaining batch atomicity and dependency independence.
|
||||||
|
- Standard-root placement and empty declarations still need explicit semantics,
|
||||||
|
as in Option B.
|
||||||
|
- Declaration capture and reuse need care: deferring work must not accidentally
|
||||||
|
let later suite mutations change installed commands or share invocation state.
|
||||||
|
|
||||||
## Ownership, collisions, and the core boundary
|
## Ownership, collisions, and the core boundary
|
||||||
|
|
||||||
Neither alternative needs to expose registry maps, an installed-config boolean,
|
None of the alternatives needs to expose registry maps, an installed-config boolean,
|
||||||
individual handler constructors, or backend objects. Ordinary registration can
|
individual handler constructors, or backend objects. Ordinary registration can
|
||||||
reject an occupied root path and commit a fully validated batch without merging
|
reject an occupied root path and commit a fully validated batch without merging
|
||||||
children. That protects installed-family ownership for both designs.
|
children. That protects installed-family ownership for all three designs.
|
||||||
|
|
||||||
Evaluate any additional reservation requirements against the accepted ownership
|
Evaluate any additional reservation requirements against the accepted ownership
|
||||||
decision, not prototype flags or incidental checks. If a reserved namespace must
|
decision, not prototype flags or incidental checks. If a reserved namespace must
|
||||||
be unavailable to ordinary application declarations before its integration is
|
be unavailable to ordinary application declarations before its integration is
|
||||||
installed, group immutability and duplicate checks alone do not express that
|
installed, group immutability and duplicate checks alone do not express that
|
||||||
rule. A narrow core installation distinction may then be justified. Both designs
|
rule. A narrow core installation distinction may then be justified. All designs
|
||||||
can accommodate it, and the final proposal should identify the exact rule it
|
can accommodate it, and the final proposal should identify the exact rule it
|
||||||
serves before selecting its public signature. Do not invent package-origin
|
serves before selecting its public signature. Do not invent package-origin
|
||||||
authentication or a general plugin framework to solve registration ownership.
|
authentication or a general plugin framework to solve registration ownership.
|
||||||
@@ -346,22 +439,50 @@ second public declaration model. Adopt it only if a concrete reservation or
|
|||||||
composition responsibility requires that distinction; module extraction alone
|
composition responsibility requires that distinction; module extraction alone
|
||||||
does not. This is a conditional extension to the alternatives, not a prerequisite.
|
does not. This is a conditional extension to the alternatives, not a prerequisite.
|
||||||
|
|
||||||
|
## Validation and declaration ownership
|
||||||
|
|
||||||
|
The following timing distinguishes the proposals; none shifts declaration errors
|
||||||
|
to command execution:
|
||||||
|
|
||||||
|
| Boundary | Option A | Option B | Option C |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| Scope/provider adapter | Record declaration | Record declaration | Record declaration |
|
||||||
|
| Integration suite validation | Integration `Register` | Integration `Command` | Core `New`/`Register` through integration-owned preparation |
|
||||||
|
| Registry and placement checks | Core registration | Core `New`/`Register` | Core `New`/`Register` |
|
||||||
|
| Provider acquisition | Selected handler | Selected handler | Selected handler |
|
||||||
|
|
||||||
|
Recommended ownership behavior: successful installation captures the declaration
|
||||||
|
metadata it needs, so later edits to suite fields or declaration slices do not
|
||||||
|
change installed commands. Application callbacks and the runtime objects they
|
||||||
|
capture retain their documented application-owned lifecycle; this is not a
|
||||||
|
promise to deep-copy arbitrary application state. The precise capture boundary
|
||||||
|
for B and C, before installation, remains an open decision below.
|
||||||
|
|
||||||
|
Empty declarations also need an explicit choice. A suite with no definition
|
||||||
|
capabilities could reasonably install nothing, but B and C then need a way to
|
||||||
|
represent that result without registering an empty standard namespace or treating
|
||||||
|
every invalid zero-value command as a no-op. An empty configuration suite may
|
||||||
|
have different semantics because scope discovery is itself an operation. These
|
||||||
|
cases remain open rather than inheriting a choice from illustrative code.
|
||||||
|
|
||||||
## Comparison
|
## Comparison
|
||||||
|
|
||||||
| Consideration | Option A: `Register` | Option B: `Command` factory |
|
| Consideration | Option A: `Register` | Option B: validated `Command` | Option C: deferred `Command` |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| Typical consumer task | Supply suite and install family | Supply suite, receive group, then install |
|
| Typical consumer task | Supply suite and install family | Supply suite, receive validated group, then install | Supply suite as a declaration to core installation |
|
||||||
| Integration exports for registration | One convenience function | One complete-group factory |
|
| Integration exports for registration | One convenience function | One complete-group factory | One deferred-declaration factory |
|
||||||
| Domain commands | Ordinary core declarations | Same |
|
| Suite errors reported at | Integration registration | Group construction | Core installation |
|
||||||
| Atomicity | Each integration registration call | Each core registration batch |
|
| Domain commands | Ordinary core declarations | Same | Same; infallible constructors not required |
|
||||||
| Standard assembly visible to callers | Integration-owned | Complete group handle exposed |
|
| Atomicity | Each integration registration call | Each core registration batch | Each core registration batch, including preparation |
|
||||||
| Pre-assembly of mixed command collections | Separate domain declarations and family calls | Directly supported |
|
| Standard assembly visible to callers | Integration-owned | Complete group handle exposed | Deferred group handle exposed |
|
||||||
| Additional core family abstraction | Only for a demonstrated reservation need | Same |
|
| Pre-assembly of mixed command collections | Separate domain declarations and family calls | Directly supported | Directly supported |
|
||||||
| Dependency isolation and lazy acquisition | Supported | Supported |
|
| Additional core mechanism | Only for demonstrated ownership needs | Same | Deferred preparation, plus any ownership mechanism |
|
||||||
|
| Dependency isolation and lazy acquisition | Supported | Supported | Supported |
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
|
|
||||||
Choose **Option A: integration-owned `Register` functions with typed suites**.
|
Prefer **Option A: integration-owned `Register` functions with typed suites and
|
||||||
|
declaration-only adapters**. Rank Option C second and Option B third.
|
||||||
The representative consumers benefit from installing standard behavior directly;
|
The representative consumers benefit from installing standard behavior directly;
|
||||||
they do not demonstrate a need to collect standard command handles or roll back
|
they do not demonstrate a need to collect standard command handles or roll back
|
||||||
all family registrations together. Per-call atomicity and discarding a failed
|
all family registrations together. Per-call atomicity and discarding a failed
|
||||||
@@ -373,12 +494,52 @@ Resolve the reservation distinction above before finalizing core signatures;
|
|||||||
add only the capability its actual responsibility requires.
|
add only the capability its actual responsibility requires.
|
||||||
|
|
||||||
Do not ship both `Register` and `Command` merely to cover every possible assembly
|
Do not ship both `Register` and `Command` merely to cover every possible assembly
|
||||||
style. Option B is a credible alternative if pre-assembly or batch installation
|
style. Options B and C are credible alternatives if pre-assembly or batch
|
||||||
becomes a demonstrated consumer requirement. Selecting it would still preserve
|
installation becomes a demonstrated consumer requirement. C reduces consumer
|
||||||
the same module and capability boundaries.
|
error-handling boilerplate but adds deferred preparation to the core contract;
|
||||||
|
B offers earlier validation with more explicit assembly steps. All preserve the
|
||||||
|
same module and capability boundaries.
|
||||||
|
|
||||||
Once this proposal is accepted, update the owning module roadmap with the chosen
|
Once this proposal is accepted, update the owning module roadmap with the chosen
|
||||||
public registration shape and reservation semantics. Its staged implementation
|
public registration shape and reservation semantics. Its staged implementation
|
||||||
plan can then specify exact declarations and validation without asking the coding
|
plan can then specify exact declarations and validation without asking the coding
|
||||||
agent to invent a family framework. Prototype-compatible names, intermediate
|
agent to invent a family framework. Prototype-compatible names, intermediate
|
||||||
buildability, and mechanical file relocation are not selection criteria.
|
buildability, and mechanical file relocation are not selection criteria.
|
||||||
|
|
||||||
|
## Remaining decisions and incomplete areas
|
||||||
|
|
||||||
|
1. **Select the registration alternative.** A remains the recommendation; C and
|
||||||
|
B remain proposals. Evaluate the full setup shown above rather than counting
|
||||||
|
only the final installation calls. No registration shape is selected here.
|
||||||
|
2. **Settle the context-free case.** The simple examples still require
|
||||||
|
`Suite[struct{}]`, a scope slice, and an unused loader argument. Decide whether
|
||||||
|
that is acceptable or whether a focused convenience entry point should accept
|
||||||
|
a loader without application context. Show its complete call site and avoid
|
||||||
|
creating a parallel configuration language just to remove a few lines.
|
||||||
|
3. **Specify empty-suite behavior.** Decide independently for configuration and
|
||||||
|
definition suites whether zero capabilities mean no installation, discovery
|
||||||
|
only, or a declaration error. If selecting B or C, define the representation
|
||||||
|
of an intentional no-op and distinguish it from an invalid command.
|
||||||
|
4. **Resolve pre-installation namespace reservations.** Identify the exact
|
||||||
|
accepted rule for names before an integration is installed, reconcile ADR
|
||||||
|
and architecture-policy language where necessary, and distinguish it from
|
||||||
|
protecting an already installed family. For B or C, also specify how standard
|
||||||
|
root placement is retained when declarations are passed through ordinary
|
||||||
|
group APIs. Add a core distinction only for the selected rule.
|
||||||
|
5. **Finalize declaration capture and reuse.** Confirm the proposed separation
|
||||||
|
of captured metadata and application-owned callback state. For B and C,
|
||||||
|
decide whether capture happens at factory invocation or installation, and
|
||||||
|
whether the returned declaration can be installed in multiple applications.
|
||||||
|
Do not infer concurrent-dispatch guarantees from declaration reuse.
|
||||||
|
6. **Complete validation details.** Define how declaration-only adapters retain
|
||||||
|
invalid wiring for the eventual validation boundary, how errors identify the
|
||||||
|
affected family or scope, and how nil loaders differ from deliberately absent
|
||||||
|
capabilities. If selecting C, specify the public preparation mechanism and
|
||||||
|
show that it validates the whole batch before registry mutation without
|
||||||
|
invoking providers or application context factories.
|
||||||
|
7. **Exercise typed customization.** Add one realistic selector/override example
|
||||||
|
showing explicit presence and scope applicability. Specify absent
|
||||||
|
`NewContext` behavior, particularly for pointer context types, and keep the
|
||||||
|
configuration and definition selector contracts appropriately distinct.
|
||||||
|
These details should support the chosen registration model without becoming
|
||||||
|
a universal integration framework.
|
||||||
|
|||||||
Reference in New Issue
Block a user