An official website of the Disclosure Foundation

Introduction

Overview

Modules

CompletenessCompellingness

Completeness

Field coverage of the records schema — what's documented, what's missing

Completeness answers: is this record well-documented? It measures how fully an observation populates the records schema — nothing more. It says nothing about whether the case is interesting; that's compellingness.

Usage

import { getCompleteness } from '@disclosureos/scoring';

const result = getCompleteness(observation);

The result

interface CompletenessResult {
  total: number;               // leaf field paths defined by the records schema
  present: number;             // how many carry a value
  percentage: number;          // present / total, 0–100 integer
  missing: string[];           // exactly which paths are absent or empty
  requiredTotal: number;       // schema-required leaf paths
  requiredPresent: number;
  requiredPercentage: number;  // 0–100 integer
}

Two percentages, because they answer different questions:

  • requiredPercentage — is this a structurally complete record? (100 for anything a factory produced.)
  • percentage — how much of the full lexicon does it use? Most real records sit well under 50, and that's fine.

The missing array is the actionable part — it's a work list for researchers improving a record:

result.missing;
// ['movement.speedKmh', 'witnesses.descriptions', 'environment.weather', ...]

What counts as present

A field is present when it carries a non-empty value: non-empty strings, non-empty arrays, objects with at least one key, and any number or boolean. null, undefined, '', [], and {} count as missing.

Derived from the schema, not hardcoded

The field inventory is derived from the records JSON Schema at runtime via deriveFieldPaths() — when the lexicon grows, completeness automatically accounts for the new fields. You can inspect or override the inventory:

import { deriveFieldPaths, getCompleteness } from '@disclosureos/scoring';

const paths = deriveFieldPaths();
// [{ path: 'temporal.date', required: true }, { path: 'movement.speedKmh', required: false }, ...]

// Score against a custom subset — e.g. your project's "minimum publishable record"
const result = getCompleteness(observation, {
  paths: paths.filter((p) => myMinimumSet.has(p.path)),
});

What completeness is not

  • Not a quality score. A complete record of a streetlight sighting is still a streetlight.
  • Not validation. An invalid record can be "complete" — validate first (Validating at Boundaries).
  • Not about the slots. Completeness measures the core record. Claims in observableAssessments and origin feed compellingness instead.

Overview

@disclosureos/scoring — completeness and compellingness, two measures that refuse to be one

Compellingness

Signal strength from claims — consensus, range, and contestedness

On this page

Usage
The result
What counts as present
Derived from the schema, not hardcoded
What completeness is not