Skip to content

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