Compellingness
Signal strength from claims — consensus, range, and contestedness
Compellingness answers: how strongly does this case bear on the two public questions — anomalous technology/biologics, and a non-mundane origin? It reads the claims in the observableAssessments and origin slots and reduces them to a transparent reference score.
Usage
import { score } from '@disclosureos/scoring';
const result = score(observation);The result
interface ScoreResult {
score: number; // 0–1 consensus point estimate
range: { low: number; high: number }; // spread across competing claims
contested: boolean; // claims disagree on direction
components: { // per-signal contributions, before weighting
technology: number;
biologics: number;
origin: number;
};
weights: CompellingnessWeights; // what produced this score
scoringVersion: string; // methodology version (e.g. '2.0.0')
}Read all three headline values together: score: 0.71 with range: { low: 0.68, high: 0.74 } is a strong consensus; score: 0.4 with range: { low: 0, high: 0.8 }, contested: true is a live dispute — and presenting it as "0.4" alone would be a lie of omission.
How the signal is computed
Observable claims convert to anomaly magnitude via evidentiary tier × confidence:
| Level | Weight |
|---|---|
not_indicated | 0 |
reported | 0.25 |
documented | 0.5 |
measured | 0.75 |
confirmed | 1.0 |
Within each domain (technology, biologics) the scorer takes the strongest established observable — the "is there any anomaly?" reduction. Six weak signals don't outscore one confirmed one.
Origin claims contribute their confidence — unless the hypothesis is prosaic (the OCS 1.1.1 branch by default), in which case the magnitude is zero. A confident "it was a balloon" classification doesn't just fail to add anomaly signal; it pulls the consensus down and can flag the case contested against anomaly claims.
Combination is a weighted average of the three signals:
import { DEFAULT_WEIGHTS } from '@disclosureos/scoring';
// { technology: 0.45, biologics: 0.35, origin: 0.2 }The default values are a reference methodology (marked @experimental) — pin your own weights if you need stable numbers across releases.
Options
const result = score(observation, {
weights: { technology: 0.5, biologics: 0.3, origin: 0.2 },
prosaicPrefixes: ['1.1.1', '2'], // also treat psychosocial as explained
evaluatorWeight: (claim) =>
claim.evidenceRefs?.length ? 1 : 0.5, // trust hook: discount uncited claims
});The evaluatorWeight hook answers who gets the most weight: trust policies (weighting verified institutions higher, discounting anonymous claims) plug in here without touching the formula. It affects the consensus point only — range and contested always report the honest spread of what evaluators actually asserted.
Ranking a corpus
import { rankByCompellingness } from '@disclosureos/scoring';
const ranked = rankByCompellingness(observations);
for (const { observation, result } of ranked.slice(0, 10)) {
console.log(observation.id, result.score, result.contested ? '⚠ contested' : '');
}This is the "one case that matters" workflow: across a large ingest, the multi-sensor, multi-witness cases float to the top — with their disputes visible.
Reading scores responsibly
- A score is a function of the claims, not the event. No claims → score 0 — "unevaluated", not "mundane".
- Always display
contestedandrangealongsidescore. - Cite
scoringVersionwhen publishing numbers; methodology versions matter. - Completeness and compellingness travel together: a compelling-but-thin record is an investigation lead, not a conclusion.