Any
At least one member source makes the cohort active.
Concepts
Cohorts turn many member sources into one derived comparison lane before comparators run. That avoids overcounting pairwise residuals when the real question is whether the group covered the target.
Problem
If a target should be covered by any two of three replicas, comparing the target to each replica separately creates three disagreement stories. The real question is whether the group, as a group, satisfied the rule over each segment.
var result = pipeline.History
.Compare("Source A vs quorum")
.Target("source-a", selector => selector.Source("source-a"))
.AgainstCohort("quorum", cohort => cohort
.Sources("source-b", "source-c", "source-d")
.Activity(CohortActivity.AtLeast(2)))
.Within(scope => scope.Window("DeviceOffline"))
.Using(comparators => comparators.Residual().Coverage())
.Run();
var uncovered = result
.CohortEvidence()
.Where(evidence => !evidence.IsActive);
Solution
Spanfold evaluates cohort activity over each aligned segment before residual, missing, coverage, or overlap rows are emitted. The result still exposes evidence metadata: active count, required count, active sources, and whether the cohort lane was active.
How it works
Spanfold first aligns the member source windows into temporal segments. For each segment, it counts active members, applies the cohort rule, records the active sources, and emits a derived against lane. Comparators then run against that derived lane, not against each member individually.
Rules
At least one member source makes the cohort active.
Every declared member must be active.
No member source may be active.
A quorum-style minimum active count.
A ceiling on how many members may be active.
A precise active count for strict agreement rules.
Evidence
Cohort rows carry metadata that explains why the derived lane was active or inactive. That metadata is useful when a quorum fails: it shows the rule, required count, observed active count, and member sources that contributed to the segment.
var inactiveSegments = result.CohortEvidence()
.Where(evidence => !evidence.IsActive)
.Select(evidence => new
{
evidence.Rule,
evidence.RequiredCount,
evidence.ActiveCount,
evidence.ActiveSources
})
.ToArray();
Use it for
Use cohorts when the comparison side is a policy over many sources: any fallback can cover the primary, all checks must agree before a release gate passes, no source may report an unsafe condition, or at least two replicas must confirm a state before it is trusted.