Skip to content

v0.12.0

Release Date: 2026-08-09

Highlights

  • ExternalAggregator Source Type: claims sourced from stats-roundup sites with no original reporting default to auto-reject, even when their excerpt verifies verbatim
  • StatisticalDetail: statistical claims carry a structured value/unit/precision/as-of-date, independent of the rendered claim text
  • TypeScript / Zod Bindings: regenerated for the new claim.statistical field

Overview

v0.12.0 closes two gaps found while auditing published case-study statistics for verifiability: sources that had no original reporting were being classified the same as any other unrecognized community source, and a claim's actual numeric value existed only inside a rendered string, with no structured way to check it against its own quoted excerpt.

New Features

ExternalAggregator Source Type

A source like an AI-generated "stats roundup" blog has no original reporting to fall back on — unlike ExternalCommunity (a named blog post, a forum thread), which is still someone's own account of something. ExternalAggregator defaults to ReliabilityLow (auto-reject) rather than the ReliabilityMedium (requires-review) an unrecognized-but-real community source gets:

claims.DefaultReliabilityForSourceType(claims.ExternalCommunity)
// → ReliabilityMedium (requires review)

claims.DefaultReliabilityForSourceType(claims.ExternalAggregator)
// → ReliabilityLow (auto-reject)

Classify by domain, not by whatever label a source claims for itself — a new helper does the domain check:

if claims.IsKnownAggregatorURL(candidateURL) {
    // reject regardless of source label or excerpt match
}

This was motivated directly by a verifiability audit: a stats-aggregator site produced at least one distorted figure and one figure contradicted by an independent source, and both had verified excerpts — the aggregator page genuinely said what was quoted. The gap wasn't excerpt matching; it was that nothing flagged the source itself as untrustworthy. See Claims Validation for the full source-type table.

StatisticalDetail

Claim.Text is a rendered string (e.g. "4.7M paid subscribers") with no structured value behind it — there was no way to query, compare, or programmatically re-check a claim's number against its Validation.External.QuotedText excerpt without re-parsing prose. ClaimStatistical claims can now carry that detail independently via Claim.Statistical:

claim.SetStatistical(
    claims.NewStatisticalDetail(4_700_000, "subscribers", claims.PrecisionExact).
        WithAsOfDate(time.Date(2026, 1, 26, 0, 0, 0, 0, time.UTC)),
)

Precision (PrecisionExact, PrecisionApproximate, PrecisionEstimated, PrecisionRange) records how exact the source's value is — "1M+" and "exactly 1,000,000" aren't the same claim. AsOfDate is deliberately distinct from Validation.External.AccessedAt: AccessedAt is when the source URL was crawled, AsOfDate is when the underlying fact was true. A claim crawled today can describe a fact from months earlier — conflating the two dates misdates the claim.

See Statistical Claims for the full walkthrough.

TypeScript / Zod Bindings

@plexusone/structured-evaluation's generated Zod schemas and TS types now include ClaimsReport's new statistical object — regenerated from the same JSON Schema (npm run generate), never hand-edited.

Backward Compatibility

Both ExternalSourceType and Claim.Statistical are additive. ExternalAggregator is a new enum value with no default classification changes for existing source types; Statistical is omitempty and nil for any claim that doesn't set it. No breaking changes.

Commits

  • 614cd5b feat(claims): add ExternalAggregator source type
  • a5d0f37 feat(claims): add StatisticalDetail for structured numeric claims
  • e1c3038 feat(ts): regenerate Zod bindings for the new statistical field
  • 01e5925 docs(claims): document ExternalAggregator and StatisticalDetail