ADR 005: Separate Capability Discovery From Capability Execution
Status
Accepted
Context
OntoBDC exposes at least two user-facing flows that operate over the same capability ecosystem:
ontobdc listontobdc run
Both commands depend on capability discovery and metadata, but they do not have the same responsibility.
At a product level, users need two different experiences:
- a read-only catalog view of what is available
- an execution flow that resolves parameters, targets a capability, validates required context, and runs it
If these concerns are collapsed into one command or one runtime layer, the system becomes harder to reason about.
In particular, a merged model would create recurring problems:
- discovery behavior could become coupled to execution side effects
- read-only inspection could accidentally inherit execution-time requirements
- execution logic could become polluted with presentation concerns meant only for catalog browsing
- future refactors might turn
listinto a thin alias ofrun, losing the distinction between “what exists” and “what can be executed now”
The current architecture already shows a deliberate separation.
The list component:
- discovers capabilities
- extracts and normalizes metadata
- renders a catalog in rich or JSON form
- does not execute capabilities
- does not evaluate capability satisfaction against CLI context
The run component:
- resolves CLI context
- loads parameter strategies
- targets a specific capability or supports selection behavior
- evaluates whether required parameters are satisfied
- executes the chosen capability
- renders execution results
This distinction is central enough to be treated as an architectural decision.
Decision
OntoBDC separates capability discovery from capability execution.
This means:
ontobdc listis the read-only discovery and catalog surfaceontobdc runis the targeting, satisfaction, and execution surface
list
The list component exists to expose the discoverable capability catalog.
Its role is to:
- load discoverable capabilities
- extract and normalize capability metadata
- present that metadata to the user
It must not:
- execute capabilities
- require capability targeting
- evaluate whether a capability is executable for the current CLI context
- mutate runtime state as part of normal listing behavior
run
The run component exists to execute capabilities.
Its role is to:
- build a runtime context from CLI input
- resolve repository and parameter inputs
- determine which capability is targeted or selectable
- evaluate whether the chosen capability has the required context
- execute that capability
- render its result
It may reuse the same capability discovery layer used by list, but it must remain a distinct execution-oriented flow.
Shared Capability Ecosystem
list and run are allowed to share:
- capability loaders
- metadata contracts
- plugin-oriented capability discovery
But they must not collapse into a single undifferentiated runtime path.
Shared discovery is acceptable.
Shared responsibility is not.
Rationale
This decision exists to preserve four important properties of the system:
- conceptual clarity
- safe read-only inspection
- execution isolation
- future maintainability
Conceptual Clarity
Users should be able to answer two different questions with two different commands:
- “What capabilities exist?”
- “Run this capability now.”
Keeping list and run distinct makes the CLI easier to understand and document.
Safe Read-Only Inspection
Catalog browsing should not require execution intent.
A user should be able to inspect the capability space without entering the execution flow, satisfying capability inputs, or triggering operational side effects.
Execution Isolation
Execution requires more than discovery.
It requires:
- context resolution
- parameter normalization
- satisfaction checks
- targeting or selection
- output rendering tied to execution
This logic belongs in run, not in the catalog flow.
Future Maintainability
The separation reduces the risk that future changes to execution behavior will unintentionally degrade discovery behavior, or vice versa.
It also supports clearer tests, clearer specs, and clearer component ownership.
Consequences
Positive
listremains a predictable read-only catalog viewrunremains focused on execution semantics- documentation can describe discovery and execution as distinct use cases
- tests can validate catalog behavior separately from execution behavior
- shared discovery infrastructure can evolve without forcing
listandruninto the same command shape
Negative
- some discovery logic is conceptually present in more than one component path
- contributors must understand the difference between metadata exposure and executable capability resolution
- there is pressure to keep the shared capability model aligned across both components
Neutral
- this does not forbid shared loaders or shared metadata normalization helpers
- this does not require that
listandrunuse completely different internals - the separation is architectural and behavioral, not a requirement for total code duplication avoidance
Alternatives Considered
Merge list Into run
Rejected because it would blur the distinction between browsing capabilities and executing them.
It would also make read-only inspection more dependent on execution-oriented logic.
Make list A Thin Alias Of run --list
Rejected because it would encourage the execution layer to absorb catalog responsibilities and would weaken the conceptual role of list as a dedicated discovery component.
Hard Split With Completely Independent Discovery Stacks
Rejected because shared capability discovery infrastructure is useful and does not conflict with architectural separation as long as component responsibilities remain distinct.
Implementation Notes
The current repository reflects this decision through:
wip/src/ontobdc/list- read-only capability listing
wip/src/ontobdc/run- runtime context resolution and execution
- shared discovery support through loader infrastructure
The current specifications that describe this distinction are:
This ADR should also be read together with:
Future Direction
This decision supports future work such as:
- expanding
listas a richer catalog without contaminating it with execution semantics - strengthening
runsatisfaction and targeting rules without turning catalog browsing into an execution preflight - sharing capability metadata infrastructure while preserving separate command identities
- preventing regressions in which discovery and execution are re-merged into one ambiguous flow