Concepts

Compare two histories by aligning their windows.

A comparison plan selects a target lane, selects one or more comparison lanes, scopes the window family, normalizes ranges, aligns segments, and emits structured rows.

Problem

Interval joins become brittle quickly.

Two providers can overlap partially, miss each other entirely, disagree only inside a segment, or leave a gap between active ranges. Hand-written interval joins tend to hide these cases in query logic.

Solution

Declare the comparison plan before emitting rows.

A comparison plan names the target lane, the against lane, the scope, the normalization policy, and the row families to emit. That order is important because it keeps the interpretation visible instead of burying it inside interval-join code.

var result = pipeline.History
    .Compare("Provider QA")
    .Target("provider-a", s => s.Source("provider-a"))
    .Against("provider-b", s => s.Source("provider-b"))
    .Within(scope => scope.Window("DeviceOffline"))
    .Normalize(n => n.RequireClosedWindows().HalfOpen())
    .Using(c => c.Overlap().Residual().Missing())
    .Run();

How

Declare the plan in the same order you reason about it.

Start with the business question: which lane is being tested, which lane should explain or cover it, and which window family is in scope. Then decide how time should be normalized before the comparator row families are selected.

Target

The lane being tested. Residual rows mean target-only evidence.

Against

The lane expected to explain, cover, or contradict the target. Missing rows mean comparison-only evidence.

Scope

The window, temporal axis, segments, and tags that define the analysis boundary.

Row families

Read rows as evidence, not just counts.

A comparison result stays useful because each row preserves the range and record ids that produced it. Counts are summaries; rows are the audit trail.

Overlap

Both target and against are active over the row range. This is the agreement evidence.

Residual

The target is active and the against side is not. This is target-only evidence and usually indicates under-coverage.

Missing

The against side is active and the target is not. This is comparison-only evidence and usually indicates the target missed something.

Comparator extensions

Coverage, gaps, containment, lead/lag, and as-of analytics build on the same aligned ranges.