Lens Families — Identity + Decision
Status & scope
- Scope: the two-engine taxonomy that frames every Prism lens. Conceptual contract — no single module; realized by the scoring engine (component.prism.scoring-engine), evidence model (component.prism.evidence-model), composition (component.prism.composition), and semantic adapter (component.prism.semantic-adapter).
- Milestone: Phase 1 (concept stable)
Purpose
Two families of governed computation share one lifecycle, one evidence model, and one platform. This spec names them, fixes the boundary between them, and defines how they compose. Every Prism lens is an instance of one family or the other.
- Identity Lens — engine: Correlation (fusion / parallax). Answers "are these records the same real-world entity?" Resolves entities across systems and organizations without moving data, exposing schemas, or revealing non-matching records. Realized in Prism by the semantic adapter (component.prism.semantic-adapter), which wraps
run_fusion(). - Decision Lens — engine: Assessment (Prism). Answers "given everything we know, what does it mean and what should we do?" Computes a weighted, multi-factor assessment from federated sources across five domain types: traversal, threat, observation, temporal, and semantic (the last wraps the Identity Lens as a scoring layer).
This is not analytics. It is decision infrastructure — governed, repeatable logic that replaces subjective judgment with auditable evidence.
Two Engines, Not One
Correlation and assessment are different operations:
- Correlation resolves identity and detects patterns across sources — is this the same entity? is something happening?
- Assessment scores meaning and options from weighted layers — how bad is it? what are the options? which is best?
Correlation output feeds assessment as a layer. Assessment never does entity resolution; correlation never scores routes or surfaces.
Why not three engines: assessment covers both impact modeling (risk surfaces, flood extent, coverage gaps) and option evaluation (routes, COAs, optimal timing). Both go through run_lens() (component.prism.scoring-engine) with different layer configurations. "What does it mean" vs "what should we do" is a lens-config difference, not an engine difference.
Source Data (feeds, queries, uploads, MCP)
│
▼
Engine 1: Correlation ── "Who is this? What's happening?"
fusion (parallax) — run_fusion()
│ CorrelationResult
▼
Engine 2: Assessment ── "What does it mean? What should we do?"
prism — run_lens()
│ AssessmentResult
▼
Promotion Boundary (DES §14)
│
▼
DES: Signal → Investigation → Edition → Attestation
Output Contracts
Each engine emits a frozen, hashable result that enters DES through the promotion boundary.
- CorrelationResult (Engine 1, fusion):
matches[](node_a_id, node_b_id, confidence, per_field_scores, blocking_key),clusters[](cluster_id, members, aggregate_confidence = min of pairwise), and arunblock (run_id, lens_id, lens_version, total_candidates, total_matches, threshold, timestamp). - AssessmentResult (Engine 2, Prism): this is the
LensResultdefined by component.prism.scoring-engine —composite_score, per-layer scores/weights/contributions, domainartifacts(route, isochrone, risk_surface, flood_extent, coverage_surface, collection_windows, action_windows, matches), optionalsignal, and a frozenevidence_block(query_hash, result_hash, lens_id, lens_version, layers_used, layer_timestamps). "AssessmentResult" is the cross-engine product name forLensResult; the field-level contract lives in component.prism.scoring-engine and component.prism.evidence-model. - COAComparison (Engine 2): ranked
AssessmentResult[]plus a recommendation, rationale, and a comparison matrix of dimensions (time, risk, exposure, distance). Defined in component.prism.scoring-engine.
Promotion to DES
A result becomes a DES Signal at the promotion boundary (DES §14 — implementation-defined). Prism's rule (component.prism.evidence-model evaluate()):
- Correlation:
confidence >= confirm→Signal(correlation.confirmed, high);>= candidate→Signal(correlation.candidate, medium); contradiction →Signal(correlation.contradiction, high). Signal carriesderived_from: [{source_type: "fusion_run", source_id: run_id}]. - Assessment:
composite_score >= confirm→Signal(output.signal_type, high);>= candidate→ medium. Signal carriesderived_from: [{source_type: "lens_run", source_id: engine_run_id}].
Each AssessmentResult can become a frozen Block (block_kind: artifact_evidence); each COAComparison seeds an Investigation with one Block per option. Pre-promotion artifacts (CorrelationResult, AssessmentResult) are not DES objects (DES §14.3).
How the Families Compose
Both families compose through the same evidence model and lifecycle.
| Identity Lens | Decision Lens | |
|---|---|---|
| Engine | Correlation (fusion) | Assessment (Prism) |
| Config | Match function, blocking strategy, field bindings | Layers, weights, cost models, thresholds |
| Output | Matches with per-field confidence | Composite score with per-layer breakdown |
| Evidence | Frozen block with match provenance | Frozen block with computation provenance |
| Governance | Pack-driven, ABAC, attestation | Same |
| DES lifecycle | Signal → Investigation → Edition → Attestation | Same |
| Composition | Correlation feeds assessment as a layer | Assessment feeds assessment via lens:// |
- Correlation feeds assessment: an Identity Lens output (entity match, cluster) becomes a scoring layer in a Decision Lens via a
correlation://source (component.prism.source-adapters). "Score this entity's risk using the resolved identity from fusion." - Assessment feeds assessment: Decision Lens outputs compose via
lens://type/namereferences, resolved by component.prism.composition (topological sort, max depth 3, circular refs rejected).
Use Cases
Each use case composes lens types from both families into one governed decision. Illustrative — these are configurations (packs + lens YAML), not new code.
| Use case | Families / lens types composed | Representative signals |
|---|---|---|
| Modern MCOO (modified combined obstacle overlay) | Traversal + Threat + Observation + Temporal, composed into one route assessment | route.disrupted, route.comms_gap, threat.spike, temporal.window_closing |
| Supply chain resilience | Traversal (multi-modal) + Threat (flood/geopolitical) + Observation (AIS/SAR) + Temporal | route.disrupted, threat.flood, observation.gap, temporal.no_window |
| Disaster response / HADR | Threat (flood D8) + Traversal (passability/SAR) + Observation (imagery/comms) + Temporal (heli windows) | threat.flood, route.blocked, observation.gap, temporal.window_open/closing |
| Portfolio credit deterioration | Decision (risk layers: DSCR, utilization, cashflow, market) + Temporal + Identity (borrower golden record) | credit.watch, credit.escalation, credit.covenant_window, credit.restructure_recommended |
| Global persistent monitoring | Observation (multi-constellation coverage, gaps, adversary exposure) + Temporal (collection-deck optimization) | observation.gap, observation.exposure, observation.window_open, temporal.window_degraded |
| GPS jamming / navigation warfare | Threat (interference/NOTAM/ADS-B) + Observation (alt-nav coverage) + Traversal (avoidance) + Temporal | threat.alert, route.disrupted, observation.degraded |
Cross-cutting in every use case: a frozen evidence block on threshold crossing (SHA-256 query + result hash, full provenance — component.prism.evidence-model), lens:// composition (component.prism.composition), and pack-driven configuration (domain / experience / accountability / lens packs).
DO NOT
- Do entity resolution inside a Decision Lens — wrap the Identity Lens via the semantic adapter instead (component.prism.semantic-adapter).
- Score routes or surfaces inside the Correlation engine — that is the Assessment engine's job.
- Introduce a third engine for "what does it mean" vs "what should we do" — it is a lens-config difference.
- Promote a raw CorrelationResult / AssessmentResult as a DES object — only promoted Signals/Blocks are DES objects.
Depends on: component.prism.composition, component.prism.evidence-model, component.prism.scoring-engine, component.prism.semantic-adapter
Realizes: product.fusion, product.lens