Record selected initial roadmap decisions

This commit is contained in:
2026-10-07 03:27:13 +00:00
parent 9d7f3b25a1
commit 0f6ced42ef
2 changed files with 90 additions and 156 deletions

View File

@@ -1,23 +1,24 @@
# Initial CommandKit feature roadmap
Status: proposed implementation target; open decisions require review before the
staged implementation plan is prepared.
Status: selected initial implementation target; ready for staged implementation
planning.
Date: 2026-10-07.
## Purpose and authority
This document defines the proposed end state of the initial library: packages,
This document defines the selected end state of the initial library: packages,
features, integration contracts, dependencies, and completion evidence. It is
prepared using [the agreed checklist](initial-plan.md). It does not sequence
implementation tasks or describe existing Go code. CommandKit currently has no Go
module or dispatcher implementation.
The [architecture policy](../policy/architecture.md) and nine accepted ADRs control
this proposal. Recommendations below fill in implementation choices; they do not
become accepted architecture merely by appearing here. Exact exported contracts
will belong in Go declarations and GoDoc; implemented operator contracts will
belong in `docs/cli.md`.
this roadmap. The delivery scope, typed API model, selector/report behavior, and
full profile inspection described here were selected during roadmap review.
These implementation choices operate within the accepted architecture. Exact
exported contracts will belong in Go declarations and GoDoc; implemented operator
contracts will belong in `docs/cli.md`.
### Requirements and traceability
@@ -48,7 +49,7 @@ evidence. Carry these controlling corrections into implementation:
- The older acquisition graph, shared-load mandates, selector inheritance rules,
illustrative Go declarations, and exact report layouts remain proposals.
## Recommended initial delivery scope
## Initial delivery scope
Deliver the dispatcher, public registration/binding API, identity/outcomes, and
inspection operations supported by ConfigKit v0.5.0 and PromptKit v0.12.0.
@@ -60,14 +61,14 @@ module still declares the dependencies used by its bundled helpers.
| Identity and discovery | `help`, command/group help, `version`, explicit CommandKit version selection |
| Configuration | `config scopes`, `validate`, `show`, `sources`, `explain`, including explicit aggregate validation/display |
| PromptKit configuration | The `promptkit` configuration scope, independently of definition inspection |
| PromptKit definitions | `promptkit show prompt`, and a documented projection for `promptkit show profile` subject to OD-3 |
| PromptKit definitions | `promptkit show prompt` and `promptkit show profile`, including effective `ExtraParams` |
| Application commands | Typed custom leaf commands, nested groups, and groups with their own runnable handler |
Recommend deferring catalog listing and semantic comparison until the owning
libraries expose the required public contracts. These are accepted standard
operations with deferred implementation, not rejected features. Their absence
must appear accurately in help and capabilities. **OD-1** considers including
upstream enhancements in the initial delivery instead.
Defer catalog listing and semantic comparison until the owning libraries expose
the required public contracts. These accepted standard operations remain future
implementation targets. Their absence must appear accurately in help and
capabilities. Initial delivery uses the current released inspection APIs; upstream
snapshot/catalog enhancements are separate follow-up work.
This scope provides meaningful configuration inspection immediately and avoids
requiring an initial consumer migration to wait for every future capability.
@@ -96,10 +97,9 @@ CommandKit or introduce a selectable backend abstraction.
### Module baseline
Recommend the following reproducible starting baseline, rather than floating
dependencies or sibling `replace` directives:
Use the following reproducible starting baseline:
| Item | Proposed baseline | Reason |
| Item | Initial baseline | Reason |
| --- | --- | --- |
| Module | `gitea.maximumdirect.net/eric/CommandKit` | Matches project identity and the existing library suite's module convention. |
| Go | `1.25.5` | Matches PromptKit v0.12.0's declared minimum; ConfigKit v0.5.0 declares 1.25.0. |
@@ -109,10 +109,11 @@ dependencies or sibling `replace` directives:
| pflag | `v1.0.9` | Match that Cobra baseline; its [module declaration](https://github.com/spf13/pflag/blob/v1.0.9/go.mod) fits the selected Go baseline. |
| YAML encoder | `go.yaml.in/yaml/v4 v4.0.0-rc.6` | Match ConfigKit's existing dependency for CommandKit-owned YAML reports. Native configuration writers remain authoritative. |
These pins are a proposal, not a claim that they are the newest releases. Resolve
and review the actual module graph and license notices when adding dependencies.
OD-1's expanded delivery alternative would require released upstream versions
containing its new capabilities and a revised capability assessment.
These pins identify the initial baseline without claiming they are the newest
releases. Resolve and review the actual module graph and license notices when
adding dependencies.
Deferred snapshot/catalog capabilities will require released upstream versions
containing the new public APIs and a revised capability assessment.
## Public API and integration model
@@ -121,7 +122,7 @@ containing its new capabilities and a revised capability assessment.
**Owner:** root. **Prerequisites:** registry and invocation contracts below.
Expose an application handle with private state and a small deliberate method
set. Recommend construction from application identity and registry options,
set. Use construction from application identity and registry options,
registration methods for groups/standard suites, and invocation with context,
arguments, and caller streams. Keep runtime dependencies in handler closures or a
separate typed execution dependency parameter; they are not parsed CLI fields.
@@ -132,7 +133,11 @@ The target concepts are identity, application/registry handle, command/group
declarations, typed bindings, presence, invocation environment, outcome, and scope
registration. Public named CommandKit types live in the root. Public ConfigKit
and PromptKit types are deliberate integration dependencies where useful.
Exact names/signatures are settled through **OD-2** before the Luna plan.
Use generic package functions/factories with explicit typed binding setters and
composable groups. Go methods cannot declare their own type parameters, so generic
entry points belong in package functions/factories. Exact names/signatures and
captured-view assembly will be specified in the staged plan using this selected
model before implementation begins.
**Completion evidence:** an external consumer uses only the root facade to
register and execute commands; public signatures, callbacks, fields, constraints,
@@ -167,7 +172,7 @@ groups work; partial standard suites expose only their available operations.
**Owners:** root for bindings/presence; adapter for backend mechanics.
**Provider requirements:** none. **Depends on:** REG-01.
Recommend generic command factories with explicit typed flag/operand setters and
Use generic command factories with explicit typed flag/operand setters and
a typed handler. Allocate the input struct for each invocation. A presence wrapper
such as `Supplied[T]` carries a value and whether it was supplied; omission differs
from an explicitly supplied empty string, false, or zero. A repeatable binding
@@ -206,18 +211,20 @@ recommended status, and supported cause identity. Standard statuses are 0, 2, an
1 respectively for success, usage, and operational failure. Preserve an
application handler's explicit domain classification and suggested status.
Recommend making root invocation the single presenter of CommandKit diagnostics.
Make root invocation the single presenter of CommandKit diagnostics.
Standard handlers return report/delivery information and safe diagnostic data;
the adapter suppresses its own automatic error printing. Use public
`configkit.WriteDiagnostics` for ConfigKit diagnostics and neutral presentation
for syntax errors. Pair diagnostics with supplied source records where useful.
Do not print an owning-library diagnostic twice through nested CommandKit paths.
Return a delivery indication so callers can distinguish a diagnostic already
presented from one whose write failed. Preserve both the operation cause and a
delivery error when both occur; do not replace either with a backend error.
Warnings alone allow success. Report or diagnostic writer errors are operational
failures and can leave partial output. **OD-2** includes this public result shape.
Return one root-owned outcome containing classification, suggested status,
operation cause, delivery failure, and a clear diagnostic-delivery indication.
This indication distinguishes a diagnostic already presented from one whose write
failed. Preserve both the operation cause and a delivery error when both occur;
do not replace either with a backend error. Invocation returns this outcome
without a separate error result. Warnings alone allow success. Report or diagnostic
writer errors are operational failures and can leave partial output.
Callbacks control their own output. Consumer guidance should recommend returning
diagnostics to the standard path and avoiding repeated presentation, without
@@ -234,13 +241,14 @@ public causes remain usable with `errors.Is`/`errors.As` where supported.
**Owner:** root. **Depends on:** registry, typed inputs, outcomes.
Recommend a typed configuration-suite factory parameterized by an
Use a typed configuration-suite factory parameterized by an
application-owned inspection-context input. It installs the standard input
bindings once, plus explicit typed application selector bindings, and scope
registrations with acquisition callbacks. A simple consumer uses an empty context
type. A complex consumer supplies campaign or other domain selection as typed
fields. Exact assembly is part of OD-2; do not require a universal untyped service
container or handler access to parser objects.
fields. Specify exact assembly in the staged plan using generic suite helpers and
small capabilities; do not require a universal untyped service container or handler
access to parser objects.
Each scope declares supported operations and obtains a captured view only on an
invocation that needs it. Use small operation-specific interfaces/callbacks:
@@ -272,19 +280,19 @@ dispatcher, manual standard-command parser, or duplicated standard report logic.
All features below belong to the root; routing, flag conversion, and help
mechanics use the adapter. Their common prerequisites are REG-01, INPUT-01,
INV-01, and OUT-01. Provider requirements and additional dependencies are stated
per feature. The following flags/report shapes are recommended implementation
targets, subject to the open decisions below.
per feature. The following flags/report shapes are selected implementation
targets for the initial standard suite.
### HELP-01 and VER-01: help and identity
- Help describes installed standard and custom commands using registry metadata.
Root bare invocation, `help [COMMAND…]`, `--help`, and `-h` follow ADR 0006.
- Recommend `version` and `version --scope commandkit`; default output is only
- Use `version` and `version --scope commandkit`; default output is only
application identity. Version subjects are separate from configuration scopes.
- Application identity is supplied at construction. Recommend obtaining embedded
CommandKit identity from Go build information, respecting module replacement
metadata; use an explicit development/unknown label when a tag is unavailable.
Do not invent a separate integer CLI version. Recommend a text default and
Do not invent a separate integer CLI version. Use a text default and
optional `--format yaml` for version records.
**Provider requirements:** identity metadata only. **Completion evidence:** help,
@@ -295,7 +303,7 @@ CommandKit selection identifies the embedded component accurately.
### CFG-01: scope metadata and selection
`config scopes` lists identifiers and supported operations in order: `app`,
`promptkit`, then additional identifiers alphabetically. Recommend text by default
`promptkit`, then additional identifiers alphabetically. Use text by default
and `--format yaml` producing `scopes: [{name, operations}]`.
All installed configuration operations use `--scope NAME`, defaulting to `app`.
@@ -316,12 +324,12 @@ validation as success. PromptKit's helper constructs/obtains a valid engine;
it does not run a prompt or probe model availability. Application domain context
validation, when needed for its inspection view, belongs in its callback.
Recommend text by default and `--format yaml` with a `scopes` sequence of completed
Use text by default and `--format yaml` with a `scopes` sequence of completed
validation records (`name`, `valid`). For `all`, preflight capability coverage,
then validate in scope order and report successful scopes as they complete;
stop on the first operational failure. Diagnostics explain the failure and the
outcome indicates incomplete completion. This timing is an initial proposal,
distinct from show's accepted preparation rule; **OD-4** considers alternatives.
outcome indicates incomplete completion. This selected validation timing preserves
show's separate preparation rule.
**Provider requirements:** validation/acquisition callback and safe diagnostics.
**Depends on:** INT-01, CFG-01. **Completion evidence:** default validates `app`;
@@ -332,12 +340,12 @@ warnings alone do not fail; no model execution is triggered by bundled handlers.
`config show` writes the selected scope's owning-library effective YAML. It must
not marshal `Result.Config`, reinterpret defaults, remove nulls, or rebuild the
native document from runtime structs. Recommend YAML as its sole initial format;
native document from runtime structs. Use YAML as its sole initial format;
accept `--format yaml` for explicitness.
For `--scope all`, acquire and complete required owning validation of every view
before writing any report bytes. Compose separate native documents in scope order,
with YAML separators and scope-label comments. Recommend `---` followed by
with YAML separators and scope-label comments. Use `---` followed by
`# scope: NAME` before each document. Single-scope show writes native output
without an added scope envelope. Preserve native content; framing must account
for any native document marker without creating accidental empty documents.
@@ -353,7 +361,7 @@ operational failure and may leave partial output.
`config sources` exposes the selected captured view's public source records.
Retain the owning source IDs, labels, paths, kinds, layers, underlay indices, and
import locations where available; missing fields do not acquire invented values.
Keep owning-library record order. Recommend readable text by default and
Keep owning-library record order. Use readable text by default and
`--format yaml` with `{scope, sources}` and explicit snake-case source fields.
**Provider requirements:** public source reader and acquisition.
@@ -363,12 +371,12 @@ reporting does not reload files or confuse provenance with effective values.
### CFG-05: path explanation
Recommend `config explain --path POINTER`, including an explicitly supplied empty
Use `config explain --path POINTER`, including an explicitly supplied empty
pointer for the root. Use public `configkit.ParsePath`; malformed pointers are
usage errors and unknown effective/historical paths are operational lookup
failures. Do not treat a native writer's empty output as successful lookup.
Text defaults to the owning `WriteExplanation` rendering. Recommend
Text defaults to the owning `WriteExplanation` rendering. Use
`--format yaml` with `{scope, path, effective, origin, history, secret_reference}`.
Preserve `present`, `redacted`, and the owner's YAML fragment in each value
snapshot; represent fragments as strings so absence/null/masked values remain
@@ -395,7 +403,7 @@ aggregate show can combine it with `app` without translating either document.
### PK-02 and PK-03: named definition inspection
Recommend these command inputs:
Use these command inputs:
```text
app promptkit show prompt ID [--version VERSION] [--format text|yaml]
@@ -414,24 +422,24 @@ input definitions in declaration order, and declared output contract. Use explic
YAML fields rather than depending on incidental Go struct serialization. An
output-contract value of `json` is domain metadata, not a JSON report format.
Profile reports include the named ID, backend-completed static target fields,
credential environment-variable name, and direct-credential requirement. Recommend
an initial documented projection excluding arbitrary `ExtraParams`, with an
explicit report indication that those parameters are omitted. Do not present an
omitted map as empty or claim this projection is a complete effective target.
**OD-3** weighs this useful current-release subset against waiting for an
owner-redacted complete result.
Profile reports include the named ID, backend-completed effective target fields,
`ExtraParams`, credential environment-variable name, and direct-credential
requirement from the existing public `ProfileInspection` result. `ExtraParams`
contains provider settings and is included in both text and YAML reports. It
requires no additional redaction or upstream inspection API for this feature.
Preserve nested parameter values when projecting the public result into the
CommandKit report schema. Credential values remain separate from these settings.
**Provider requirements:** public `InspectPrompt`/`InspectProfile` respectively;
each capability can be registered independently. **Depends on:** INT-01 and the
chosen report projection. **Completion evidence:** text and YAML preserve selected
public metadata; profile credentials are reported as requirements/references;
unknown IDs and cancellation retain supported public error identity; help never
constructs an engine.
public report projection. **Completion evidence:** text and YAML preserve public
metadata and effective provider parameters; profile credentials are reported as
requirements/references; unknown IDs and cancellation retain supported public
error identity; help never constructs an engine.
## Selectors, reports, and ownership
Recommend a shared standard selection input for acquisition-bearing inspection
Use a shared standard selection input for acquisition-bearing inspection
commands, carrying presence-aware `--config` and singleton `--overlay`.
Application callbacks interpret their values using the owning loader. Omission
delegates discovery/default selection; an explicitly empty overlay can represent
@@ -446,10 +454,10 @@ inspection and to engine acquisition derived from that application view. Reject
explicit selectors that do not apply to any selected scope with a usage diagnostic;
for `all`, route each selector to the scopes that declare it. Metadata/help should
state applicability. Validate declared selector combinations before acquisition;
domain lookup/validation remains operational. **OD-4** reviews this proposed
selection contract. Do not infer application-specific campaign or session policy.
domain lookup/validation remains operational. Do not infer application-specific
campaign or session policy.
Recommend text defaults for CommandKit-owned summaries and YAML alternatives;
Use text defaults for CommandKit-owned summaries and YAML alternatives;
`config show` is native YAML. CommandKit owns report schemas for summaries,
source/explanation projections, and definition reports. Owning libraries own the
native documents and safe values. Select schema fields deliberately and document
@@ -490,7 +498,7 @@ evidence snapshots, not build dependencies.
| Sources/diagnostics | Public result/load-error source and diagnostic records | Configuration-inspection sources/diagnostics | Include CFG-04 and OUT-01. |
| Safe path explanation | `Explain`, `WriteExplanation`, public `Path` | Equivalent configuration-inspection methods | Include CFG-05. |
| Named prompt metadata | Outside its resource domain | `Engine.InspectPrompt` and `PromptInspection` | Include PK-02. |
| Named effective profile target | Outside its resource domain | `Engine.InspectProfile`; credential-reference fields are documented, but `ExtraParams` is arbitrary copied data | Include the OD-3 projection only after its contract is selected. |
| Named effective profile target | Outside its resource domain | `Engine.InspectProfile` exposes the effective target including copied `ExtraParams`, plus credential requirements/reference names | Include PK-03 using the existing public result, including provider parameters. |
| Catalog enumeration | Outside its resource domain | No public prompt/profile enumeration API found | Defer CAT-01; recommend upstream captured catalog inspection. |
| Safe full semantic comparison snapshot | No dedicated public structured tree plus full sensitivity/coverage contract found | No corresponding configuration snapshot API found | Defer DIFF-01; recommend upstream safe snapshot support. |
@@ -514,9 +522,6 @@ owning-library agreement and design, rather than assuming masks imply equality.
- **CAT-01:** list captured prompt/version entries and named profiles through public
owning catalog APIs; deterministic reports describe actual loaded definitions.
Do not infer catalogs from configuration YAML or inspect sibling internals.
- **Complete PK-03:** obtain a safe owner-defined profile projection, including
provider parameters and their disclosure treatment, before expanding the initial
report beyond its selected coverage.
Do not create empty handlers, pretend capabilities, or unused public snapshot
types for these deferred targets. Future upstream contracts should inform their
@@ -533,7 +538,7 @@ this roadmap. Prefer existing public owning writers over porting their renderers
| [Notarius configuration handlers](../../../notarius/internal/cli/configkit_commands.go): `runConfigEffective`, `runConfigExplain` | Load an application result and call native ConfigKit writers; canonical path parsing and lookup handling | Retain the acquisition-to-writer pattern. Replace application scopes, manual flag sets, output/status handling, and loader coupling with INT-01/CFG-03/05. The application keeps its loader and domain selection. |
| Same file: `runConfigProfile`, `runConfigValidate` | Named profile inspection and application-specific validation examples | Evaluate inputs and callback needs. Their JSON report, private wrappers, and runtime/domain validation are not standard contracts. |
| [Scriptorium inspection dispatch](../../../scriptorium/internal/adapter/cli/inspect.go): `inspectCommand` | Lazy engine acquisition and named inspection followed by formatting | Keep upstream method use. Replace private dispatch, `context.Background`, output-file behavior, old command paths, and integer-status plumbing with caller context, streams, and outcomes. |
| [Scriptorium report projections](../../../scriptorium/internal/format/inspection.go): `FormatPromptInspection`, `FormatProfileInspection` | Explicit prompt/profile field projection and readable presentation | Prompt DTO fields are a useful starting inventory. Replace JSON output with YAML and select OD-3's profile coverage; its raw `ExtraParams` serialization must not become an assumed redacted report. |
| [Scriptorium report projections](../../../scriptorium/internal/format/inspection.go): `FormatPromptInspection`, `FormatProfileInspection` | Explicit prompt/profile field projection and readable presentation | Prompt/profile DTO fields are useful starting inventories. Replace JSON output with YAML and include the public effective `ExtraParams` values in profile reports. |
| [Narratio comparison](../../../narratio/internal/app/config_diff.go): `ConfigDiff`, `configDiffWithDependencies` and comparison helpers | Independent resolved selections, deterministic path records, and add/remove/change presentation | Evidence for future DIFF-01. Its application projection/digests, overlay-only operands, shared campaign policy, and absence of ADR 0008 sensitivity-gap semantics require redesign; no initial direct port is proposed. |
Recommend implementing the small integration glue from these public contracts,
@@ -569,7 +574,7 @@ or standard report projection, revisit the API before making the Luna plan.
## Explicit deferrals
In addition to DIFF-01, CAT-01, and complete profile projection, defer JSON report
In addition to DIFF-01 and CAT-01, defer JSON report
output, shell completion, output-file management, backend selection, a plugin
framework, general dependency injection, concurrent-dispatch guarantees, and
implementation of additional library families. None is needed to prove the
@@ -584,8 +589,8 @@ build matrix.
## Completion and implementation-plan handoff
The initial target is complete when the included feature IDs have their stated
observable behavior and evidence, and the selected open-decision outcomes are
reflected consistently in the API and CLI contracts.
observable behavior and evidence, and the selected roadmap choices are reflected
consistently in the API and CLI contracts.
Use proportionate deterministic, offline behavioral evidence under the
[testing policy](../policy/testing.md): public consumer tests with the real adapter
@@ -608,83 +613,10 @@ Maintain these substantive documents/artifacts as implementation lands:
- Contributor commands and orientation updates once the Go module and validation
commands actually exist; preserve existing policy ownership.
Before writing the staged Luna plan, review the proposed delivery scope and
resolve OD-1–4. Translate included IDs into ordered tasks with prerequisites,
precise API/CLI deliverables, and completion checks. Carry deferred IDs forward
without scaffolding them. That subsequent plan should make the selected public
The delivery scope, typed API/outcome model, full profile coverage, and
selector/validation behavior have been selected. Translate included IDs into
ordered tasks with prerequisites, precise API/CLI deliverables, and completion
checks. Specify exact Go declarations, binding helpers, captured-view assembly,
and stream placement in that staged plan using the selected model. Carry deferred
IDs forward without scaffolding them. The plan should make the selected public
contracts concrete enough that the implementation agent need not invent them.
## Open Decisions
### OD-1: current-release delivery or upstream expansion first?
**Recommendation:** adopt the initial scope above against released ConfigKit
v0.5.0/PromptKit v0.12.0; defer DIFF-01 and CAT-01. Most duplicated inspection
infrastructure can be removed now. Capability-based assembly already accommodates
later additions without requiring every family/scope to acquire those verbs.
**Alternative:** include public safe snapshots and catalog inspection in upstream
work before completing the initial CommandKit implementation. This delivers the
broader standard suite together and avoids an interim subset. It expands the
initial effort into multiple independently released libraries and requires their
data contracts, versions, and comparison selection rules to be selected first.
Choose it if comparison/catalog inspection are required for initial adoption.
### OD-2: exact typed registration and outcome API shape
**Recommendation:** use an application handle, composable groups, generic command
factories with explicit typed binding setters, and generic standard-suite helpers.
Handlers receive typed inputs plus a separate invocation environment; return a
root-owned outcome carrying classification, suggested status, cause, and delivery
information. Reuse public upstream inspection records through small capabilities.
This supports an ordinary input struct and avoids parallel consumer parsing.
Go generic methods are unavailable, so generic entry points should be package
functions/factories rather than methods with their own type parameters.
**Alternative:** use typed descriptor/builders that collect bindings before a
non-generic registration call. This can offer readable fluent assembly and stronger
construction guidance, but adds builder surface and potentially more conversion
machinery. Evaluate it against both consumer examples before choosing signatures.
For failure delivery, recommend one outcome carrying both the operation cause and
delivery failure, with a clear diagnostic-delivery indication. A viable alternative
is `(Outcome, error)`, with the error reserved for invocation/delivery failures.
That follows familiar Go conventions but needs a precise rule preventing the same
failure from being ambiguously represented in both results. Resolve this alongside
the constructor, binding helpers, captured-view assembly, and stream placement;
neither signature is approved by this roadmap.
### OD-3: initial profile-report coverage
**Recommendation:** ship a documented current-API projection of named profile
identity, static effective target fields, and credential requirements/reference
names. Explicitly report that arbitrary provider parameters are omitted. This
exposes useful backend-completed inspection now while keeping the coverage honest.
It does not impose a new upstream confidentiality guarantee or promise complete
effective-profile output.
**Alternative:** defer PK-03 until PromptKit provides an owner-redacted complete
profile inspection representation with provider-parameter treatment. This yields
one fuller report contract and keeps sensitivity decisions entirely upstream,
but delays useful named-profile inspection and expands upstream prerequisites.
Directly serializing all current `ExtraParams` does not establish safe inspection
semantics and is not a substitute for choosing a disclosure contract.
### OD-4: standard selector and validation-report behavior
**Recommendation:** use presence-aware `--config` and singleton `--overlay`, plus
explicit typed context bindings with scope applicability. Use `--path` for
configuration explanation and operands for named definitions. Validate coverage
and declared input combinations before acquisition. For aggregate validation,
report completed scopes in order and stop at the first operational failure.
Use the proposed text/YAML schemas above. This is a small consistent initial
operator surface; native show retains its separate preparation requirement.
**Alternative:** expose distinct application/engine source flags and acquire all
validation results before emitting one aggregate report. Separate selectors make
independent source selection explicit and complete validation results are useful
for tooling. They increase input vocabulary and need a defined aggregation/error
model. Adopt these where actual consumers need independent roots or comprehensive
validation in one invocation, rather than assuming every engine follows the app
selection. A narrower variant retains shared selectors and only changes validation
aggregation. Decide these report/selection details before publishing contracts.