Lens Composition
Status & scope
- Module:
lens/composer.py - Milestone: Phase 2 (complete)
Purpose
Resolve lens://type/name references between lenses. A traversal lens consumes threat and observation outputs as cost layers — declared in YAML, resolved by the composer. Dependency ordering with circular reference detection.
Public API
is_lens_reference(source) → bool
- True if source starts with
lens://.
get_references(spec) → list[str]
- Extract all
lens://references from a spec's layers.
resolve_dependencies(spec, lens_registry) → list[LensSpec]
- Topological sort of lens dependency graph.
- Max depth 3. Circular references raise ValueError.
Composition Pattern
# Traversal lens consuming threat + observation outputs
layers:
- name: flood_risk
source: "lens://threat/flood_extent_24h" # output of another lens
weight: 0.4
cost_model: linear_scale
- name: sat_exposure
source: "lens://observation/adversary_coverage"
weight: 0.3
cost_model: linear_scale
Orchestrator executes dependencies first, passes output as layer_data.
File Layout
lens/
composer.py ← is_lens_reference, get_references, resolve_dependencies
Test References
- tests/test_integration.py — composition tests, circular detection
DO NOT
- Allow circular references — max depth 3
- Execute compositions implicitly — caller controls execution order
- Build a DAG executor — this is dependency resolution, not workflow
Depends on: component.prism.scoring-engine, component.prism.universal-lens-parser
Required by: component.prism.incremental-updates, component.prism.lens-families