SPEC 006 - Run CLI Context Resolution
Status
- Status: Working specification of the current
ontobdc runCLI context model - Scope:
wip/src/ontobdc/run/adapter/context.pyand the parameter strategies loaded into it - Audience: maintainers and contributors working on CLI parsing, capability targeting, and runtime extensibility
1. Purpose
This specification describes how the ontobdc run context is built from CLI arguments before capability selection or execution happens.
The context layer exists to:
- normalize raw CLI arguments into structured parameters
- preserve unknown arguments for later inspection
- provide a repository root to downstream execution flows
- support both built-in and project-defined parameter strategies
- determine whether a capability has enough required inputs to be considered executable
This document focuses on the behavior currently exercised by:
test/src/ontobdc/run/adapter/test_context.pytest/src/ontobdc/run/adapter/test_context_config.py
2. Source Of Truth
This specification is derived from the current implementation under:
wip/src/ontobdc/run/adapter/context.pywip/src/ontobdc/shared/adapter/plugin.pywip/src/ontobdc/run/plugin/parameter/*.py
The active automated tests covering this behavior are:
test/src/ontobdc/run/adapter/test_context.pytest/src/ontobdc/run/adapter/test_context_config.py
3. Runtime Role
The run context layer is the normalization boundary between:
- raw terminal input such as
argv - the capability execution layer
It does not execute a capability.
Its responsibility is to create a CliContextPort instance whose parameter map can later be used to:
- identify a targeted capability
- resolve repository location
- expose parsed filters and flags
- verify capability input satisfaction
In practice, this means the context layer is the parsing and enrichment stage of ontobdc run.
4. Core Model
4.1 CliContextAdapter
The current concrete context object is CliContextAdapter.
It stores:
raw_args- the original
argvsequence unprocessed_args- all arguments except
argv[0], progressively reduced as strategies consume known flags and values parameters- a dictionary keyed by logical parameter name, with values shaped as metadata dictionaries
4.2 Parameter Map Contract
Each parsed parameter is stored under a logical key such as:
capability_idexporthelprepositorylimitstartfile_namefile_typeraw_text_pathaction_onlyinclude_action
Each value is a dictionary and may contain:
valueparam_uriuri- any other strategy-defined metadata
The current implementation does not enforce a single rigid schema beyond using dictionaries.
4.3 Convenience Properties
The adapter currently exposes two derived properties:
target_capability_id- returns
parameters["capability_id"]["value"]when available is_capability_targeted- returns
Truewhentarget_capability_idis notNone
This means a malformed --id sequence may still create a capability_id entry while leaving the target unresolved.
5. Root Path Resolution
The context adapter also exposes root_path.
Current behavior:
- start from
os.getcwd() - walk upward until a
.__ontobdc__/config.yamlfile is found - return that directory if found
- otherwise return the current working directory
This root discovery is used later by parameter strategies and by the resolver when looking for project-local context configuration.
The current tests validate both:
- explicit repository override via CLI flags
- fallback to current working directory when no repository flag is present
6. Resolution Pipeline
6.1 Resolver Entry
The runtime entrypoint for context building is CliContextResolver.resolve(argv).
The current pipeline is:
- Create a
CliContextAdapter(argv). - Load built-in parameter strategies using
ParameterLoader. - Look for
.__ontobdc__/config.yamlundercontext.root_path. - If present, load project-defined custom strategy packages from
capability.parameter. - Append discovered custom strategies to the built-in strategy list.
- Execute all strategies sequentially against the same mutable context.
- Return the resulting context.
6.2 Ordering Semantics
The resolver is designed around strategy composition.
The current tests show that:
- supported parameters can appear in mixed order
- the final context is order-tolerant for the supported flag set
This does not mean all parameter combinations are commutative in an abstract sense.
It means the current built-in strategy set is robust to the tested permutations.
7. Built-In Strategy Model
Built-in strategies are discovered through ParameterLoader, which scans plugin packages under the current OntoBDC package tree.
The active built-in parameter strategy modules currently include:
action_only.pycapability.pyexport.pyfile_filter.pyhelp.pyinclude_action.pypagination.pyroot_path.pytext_file.py
Each strategy:
- inspects
context.unprocessed_args - extracts the flags it recognizes
- writes normalized values into
context.parameters - removes consumed arguments from
context.unprocessed_args
8. Current Built-In Parameters
The tests in test_context.py currently validate the following built-in behaviors.
8.1 Capability Targeting
Flag:
--id <value>
Behavior:
- stores
capability_id - sets
target_capability_id - marks
is_capability_targetedasTrue
If --id is missing a usable value:
capability_idis still registered- its
valuebecomesNone is_capability_targetedbecomesFalse
8.2 Export Format
Flag:
--export <json|rich>
Behavior:
- stores
export - only accepts
jsonorrich
Failure behavior:
- raises
ValueErrorfor invalid formats - raises
ValueErrorfor missing values
8.3 Help
Flags:
-h--help
Behavior:
- stores
help=True - removes help flags from
unprocessed_args
8.4 Repository Selection
Flags:
--root-path <path>--repository <path>
Behavior:
- stores
repositoryas aLocalDirectoryRepository --root-pathhas priority over--repository- when neither flag is given, the repository defaults to the current working directory discovered by the adapter
8.5 Pagination
Flags:
--start <integer>--limit <integer>
Behavior:
- stores
startandlimitas integers
Failure behavior:
- raises
ValueErrorfor invalid numeric values - raises
ValueErrorfor missing values
8.6 File Filtering
Flags:
--file-name <pattern>--file-type <type[,type...]>
Behavior:
- stores
file_nameas a string - stores
file_typeas a list of strings
8.7 Raw Text File
Flag:
--text-file <path>
Behavior:
- stores
raw_text_path
8.8 Action Flags
Flags:
--action-only-a
Behavior:
--action-onlystoresaction_only=True-aparticipates in include-action semantics and storesinclude_action=True
The include-action strategy also supports additional aliases such as -auc, -uca, and --all, even though those aliases are not exercised directly by the two adapter tests documented here.
9. Unknown Argument Preservation
One explicit contract of the resolver is preservation of unknown arguments.
If an argument is not recognized and consumed by any strategy:
- it remains in
context.unprocessed_args
This is important because:
- the parser is intentionally strategy-driven rather than monolithic
- downstream layers can still inspect leftover arguments
- the system can distinguish between recognized parameters and unhandled input
The main mixed-parameter test currently verifies that after all known strategies run:
- only the truly unknown argument remains
10. Project-Defined Custom Strategies
10.1 Configuration Source
The resolver supports loading custom parameter strategies from:
.__ontobdc__/config.yaml
The active configuration key is:
capability.parameter
Expected shape:
capability:
parameter:
- some.python.package
Each listed entry is expected to be a Python package, not just a single module file.
10.2 Discovery Model
For each configured package:
- Import the package.
- Ignore it if it is not package-like, meaning it has no
__path__. - Walk submodules inside that package.
- Import each submodule.
- Instantiate every class that subclasses
CliContextStrategyPort. - Append those strategy instances to the resolver pipeline.
10.3 Execution Model
Custom strategies execute in the same mutable context model used by built-in strategies.
That means a custom strategy may:
- inspect
unprocessed_args - add parameters
- remove consumed flags and values
The dedicated config test validates this with a temporary package providing a CustomFlagStrategy that parses:
--custom-flag <value>
10.4 Legacy Keys
The resolver currently ignores legacy configuration keys such as:
parametersstrategies
Only capability.parameter is active in the current design.
11. Error Tolerance In Config Loading
The custom strategy loading layer is intentionally tolerant.
Current behavior:
- if
config.yamldoes not exist, continue with built-in strategies only - if YAML is invalid, ignore the failure and continue
- if a configured package cannot be imported, ignore the failure and continue
- if a configured entry resolves to a non-package module, ignore it
This tolerance is validated directly by test_context_config.py.
The purpose of this behavior is runtime resilience:
- project-local extension must not break the base resolver entirely
12. Capability Satisfaction Contract
Beyond raw parsing, CliContextResolver also exposes is_satisfied_by(capability, context).
Current behavior:
- Read
capability.METADATA.input_schema.properties. - Collect every property whose metadata contains
required: True. - For each required property:
- fail if the parameter key does not exist in the context
- fail if the parameter exists but its
valueisNone - Return
Trueonly when all required parameters are present with non-null values
This means context satisfaction is currently:
- metadata-driven
- based on logical parameter names
- strict for missing and null required values
13. Operational Implications
The current context model implies the following runtime design choices.
13.1 The Context Layer Is Extensible
New CLI parsing behavior does not require rewriting a central parser.
Instead, contributors can:
- add a new parameter strategy plugin
- or register a project-local custom strategy package through
config.yaml
13.2 Parsing Is Partially Strict
Some invalid parameter states raise explicit exceptions, especially for:
- export format
- pagination values
Other states are tolerated and preserved, especially for:
- unknown flags
- missing config
- custom strategy loading failures
13.3 Repository Resolution Is Always Present
Even when no repository flag is supplied, the resolver still injects a repository object.
This makes downstream capability code simpler because a repository parameter is expected to exist after normal resolution.
14. Test Coverage Summary
14.1 Covered By test_context.py
- mixed built-in parameter parsing
- unknown argument preservation
- capability targeting state
- repository alias behavior
- repository default behavior
- missing capability value behavior
- invalid export handling
- missing export value handling
- invalid limit handling
- missing start value handling
14.2 Covered By test_context_config.py
- loading custom strategies from
capability.parameter - execution of a custom strategy against the context
- ignoring legacy config keys
- ignoring missing custom packages
- tolerating invalid YAML
- falling back to built-in strategies when config is absent
- ignoring non-package custom modules
15. Current Limitations
The current implementation has some notable limitations.
- Strategy ordering is implicit; there is no explicit priority model.
- Invalid custom strategy definitions are silently ignored.
- Error reporting for config-driven extension is intentionally minimal.
- The resolver mutates a shared context object rather than returning immutable snapshots.
- Satisfaction checks only inspect
required: True; they do not validate types, enums, or richer schema rules.
16. Guidance For Contributors
When adding a new CLI parameter to ontobdc run, the current recommended path is:
- Create a new strategy under
wip/src/ontobdc/run/plugin/parameter. - Parse only the flags owned by that strategy.
- Write a normalized logical parameter key into the context.
- Remove consumed args from
unprocessed_args. - Add focused tests:
- a strategy-level test when appropriate
- a resolver-level test when integration with the aggregate context matters
When adding a project-local extension, use:
capability:
parameter:
- your.package.name
and ensure that package exports submodules containing classes that subclass CliContextStrategyPort.