claims

package
v0.13.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package claims provides types for claim extraction and source validation. This enables verification that factual claims in documents are properly sourced (external references) or objectively validated (internal evidence).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HasErrors added in v0.13.0

func HasErrors(findings []LintFinding) bool

HasErrors reports whether any finding is error severity.

func HasWarnings added in v0.13.0

func HasWarnings(findings []LintFinding) bool

HasWarnings reports whether any finding is warning severity.

func IsFresh added in v0.13.0

func IsFresh(c Claim, criteria ClaimsCriteria, now time.Time) bool

IsFresh reports whether c's statistical value is recent enough to satisfy criteria.MaxClaimAge, measured from now. Always true when: the requirement is disabled (MaxClaimAge <= 0), c has no Statistical detail, or its AsOfDate is unset — age is unknown, not stale, so an unset date is never penalized.

func IsSufficientlyCorroborated added in v0.13.0

func IsSufficientlyCorroborated(c Claim, criteria ClaimsCriteria) bool

IsSufficientlyCorroborated reports whether c has enough independent sources to satisfy criteria.MinCorroboratingSources, counting c's own source plus each entry in c.RelatedClaimIDs. Always true when the requirement is disabled (MinCorroboratingSources <= 1), or when criteria.CorroborationCategories is set and does not include c.Category.

Types

type Claim

type Claim struct {
	// ID is the unique identifier for this claim.
	ID string `json:"id"`

	// Text is the exact claim text from the document.
	Text string `json:"text"`

	// Location identifies where the claim appears.
	Location Location `json:"location"`

	// Category categorizes the type of claim.
	Category ClaimCategory `json:"category"`

	// Validation describes how the claim is validated.
	Validation *Validation `json:"validation,omitempty"`

	// Statistical holds structured numeric detail for statistical claims
	// (Category == ClaimStatistical) — the value and unit behind Text, kept
	// separate so the number itself is queryable rather than only existing
	// inside a formatted string. Nil for non-statistical claims.
	Statistical *StatisticalDetail `json:"statistical,omitempty"`

	// Verdict is the validation result.
	Verdict Verdict `json:"verdict"`

	// Rationale explains the verdict.
	Rationale string `json:"rationale,omitempty"`

	// RelatedClaimIDs are IDs of related claims.
	RelatedClaimIDs []string `json:"relatedClaimIds,omitempty"`
}

Claim represents a factual claim extracted from a document.

func NewClaim

func NewClaim(id, text string, category ClaimCategory, location Location) *Claim

NewClaim creates a new claim with the given details.

func (*Claim) AddRelatedClaim

func (c *Claim) AddRelatedClaim(claimID string) *Claim

AddRelatedClaim adds a related claim ID.

func (*Claim) IsBlocking

func (c *Claim) IsBlocking() bool

IsBlocking returns true if the claim blocks publication.

func (*Claim) IsVerified

func (c *Claim) IsVerified() bool

IsVerified returns true if the claim is verified.

func (*Claim) NeedsReview

func (c *Claim) NeedsReview() bool

NeedsReview returns true if the claim requires human review.

func (*Claim) SetStatistical added in v0.12.0

func (c *Claim) SetStatistical(detail *StatisticalDetail) *Claim

SetStatistical attaches structured numeric detail to the claim. Meaningful when Category is ClaimStatistical; harmless (but not rendered by convention) otherwise.

func (*Claim) SetValidation

func (c *Claim) SetValidation(v *Validation) *Claim

SetValidation sets the validation and computes the verdict.

func (*Claim) SetVerdict

func (c *Claim) SetVerdict(verdict Verdict, rationale string) *Claim

SetVerdict sets the verdict with rationale.

type ClaimCategory

type ClaimCategory string

ClaimCategory categorizes the type of claim.

const (
	// ClaimMetadata is metadata about the subject (e.g., identifiers, versions).
	ClaimMetadata ClaimCategory = "metadata"

	// ClaimTechnicalFinding is a technical observation or finding.
	ClaimTechnicalFinding ClaimCategory = "technical-finding"

	// ClaimFrameworkMapping maps to a standard framework (e.g., taxonomy IDs).
	ClaimFrameworkMapping ClaimCategory = "framework-mapping"

	// ClaimRiskAssessment is a risk or impact assessment.
	ClaimRiskAssessment ClaimCategory = "risk-assessment"

	// ClaimTimeline is a temporal claim (dates, events).
	ClaimTimeline ClaimCategory = "timeline"

	// ClaimStatistical is a statistical or numeric claim.
	ClaimStatistical ClaimCategory = "statistical"

	// ClaimGuidance is a recommendation or guidance claim.
	ClaimGuidance ClaimCategory = "guidance"

	// ClaimAttribution credits a source or author.
	ClaimAttribution ClaimCategory = "attribution"
)

type ClaimsCounts

type ClaimsCounts struct {
	Total       int `json:"total"`
	Verified    int `json:"verified"`
	Unverified  int `json:"unverified"`
	NeedsReview int `json:"needsReview"`
	Rejected    int `json:"rejected"`
}

ClaimsCounts tracks claims by verdict.

func CountClaims

func CountClaims(claims []Claim) ClaimsCounts

CountClaims counts claims by verdict.

type ClaimsCriteria

type ClaimsCriteria struct {
	// RequireAllVerified requires all claims to be verified.
	RequireAllVerified bool `json:"requireAllVerified"`

	// AllowSubjectiveWithDisclaimer permits subjective claims if acknowledged.
	AllowSubjectiveWithDisclaimer bool `json:"allowSubjectiveWithDisclaimer"`

	// AllowNeedsReview permits claims that need review (conditional pass).
	AllowNeedsReview bool `json:"allowNeedsReview"`

	// MinReliabilityTier is the minimum acceptable reliability for external sources.
	MinReliabilityTier ReliabilityTier `json:"minReliabilityTier"`

	// RequireReproducible requires internal validations to be reproducible.
	RequireReproducible bool `json:"requireReproducible"`

	// RequiredCategories are claim categories that must have at least one verified claim.
	RequiredCategories []ClaimCategory `json:"requiredCategories,omitempty"`

	// MinCorroboratingSources is the minimum number of independent sources
	// required for a verified claim to be treated as sufficiently
	// corroborated, counting the claim's own source plus each entry in its
	// RelatedClaimIDs. 0 or 1 disables the requirement — a single source is
	// always sufficient. See IsSufficientlyCorroborated.
	MinCorroboratingSources int `json:"minCorroboratingSources,omitempty"`

	// CorroborationCategories restricts MinCorroboratingSources to specific
	// claim categories (e.g. only ClaimStatistical). An empty slice applies
	// the requirement to every category.
	CorroborationCategories []ClaimCategory `json:"corroborationCategories,omitempty"`

	// MaxClaimAge is how old a verified statistical claim's
	// StatisticalDetail.AsOfDate may be, relative to now, before it is
	// treated as stale (presented as current when it no longer is). Zero or
	// negative disables the requirement — no claim is ever too old. A claim
	// with no Statistical detail, or one whose AsOfDate is unset, is never
	// flagged: age is unknown, not stale. See IsFresh.
	MaxClaimAge time.Duration `json:"maxClaimAge,omitempty"`
}

ClaimsCriteria defines requirements for claim validation approval.

func DefaultClaimsCriteria

func DefaultClaimsCriteria() ClaimsCriteria

DefaultClaimsCriteria returns standard criteria.

func StrictClaimsCriteria

func StrictClaimsCriteria() ClaimsCriteria

StrictClaimsCriteria returns strict criteria for high-stakes publications.

type ClaimsDecision

type ClaimsDecision struct {
	// Status is the decision outcome.
	Status ClaimsDecisionStatus `json:"status"`

	// Passed indicates if the claims validation passed.
	Passed bool `json:"passed"`

	// Rationale explains the decision.
	Rationale string `json:"rationale"`

	// Counts summarizes claims by verdict.
	Counts ClaimsCounts `json:"counts"`
}

ClaimsDecision represents the validation decision for claims.

func EvaluateClaims

func EvaluateClaims(claims []Claim, criteria ClaimsCriteria) ClaimsDecision

EvaluateClaims checks claims against criteria.

type ClaimsDecisionStatus

type ClaimsDecisionStatus string

ClaimsDecisionStatus represents the decision outcome.

const (
	// ClaimsDecisionPass indicates all claims are verified.
	ClaimsDecisionPass ClaimsDecisionStatus = "pass"

	// ClaimsDecisionConditional indicates some claims need review.
	ClaimsDecisionConditional ClaimsDecisionStatus = "conditional"

	// ClaimsDecisionFail indicates unverified or rejected claims exist.
	ClaimsDecisionFail ClaimsDecisionStatus = "fail"
)

type ClaimsMetadata

type ClaimsMetadata struct {
	// Document is the filename or path being validated.
	Document string `json:"document"`

	// DocumentID is the document identifier.
	DocumentID string `json:"documentId,omitempty"`

	// DocumentTitle is the document title.
	DocumentTitle string `json:"documentTitle,omitempty"`

	// DocumentVersion is the document version.
	DocumentVersion string `json:"documentVersion,omitempty"`

	// GeneratedAt is when the report was created.
	GeneratedAt time.Time `json:"generatedAt"`

	// GeneratedBy identifies what created this report.
	GeneratedBy string `json:"generatedBy,omitempty"`

	// ValidatedBy identifies who validated the claims.
	ValidatedBy string `json:"validatedBy,omitempty"`
}

ClaimsMetadata contains report identification.

type ClaimsReport

type ClaimsReport struct {
	// Schema is the JSON Schema URL.
	Schema string `json:"$schema,omitempty"`

	// Metadata contains report identification.
	Metadata ClaimsMetadata `json:"metadata"`

	// Claims are the extracted and validated claims.
	Claims []Claim `json:"claims"`

	// Summary provides aggregated statistics.
	Summary ClaimsSummary `json:"summary"`

	// Criteria defines the pass requirements.
	Criteria ClaimsCriteria `json:"criteria"`

	// Decision is the validation outcome.
	Decision ClaimsDecision `json:"decision"`
}

ClaimsReport is the report for claim validation.

func NewClaimsReport

func NewClaimsReport(document string) *ClaimsReport

NewClaimsReport creates a new claims report.

func (*ClaimsReport) AddClaim

func (r *ClaimsReport) AddClaim(c Claim)

AddClaim adds a claim to the report.

func (*ClaimsReport) Evaluate

func (r *ClaimsReport) Evaluate() ClaimsDecision

Evaluate computes the summary and decision.

func (*ClaimsReport) Finalize

func (r *ClaimsReport) Finalize()

Finalize computes all derived fields.

func (*ClaimsReport) GenerateSummaryText

func (r *ClaimsReport) GenerateSummaryText() string

GenerateSummaryText creates a human-readable summary.

func (*ClaimsReport) GetClaim

func (r *ClaimsReport) GetClaim(claimID string) *Claim

GetClaim returns a claim by ID, or nil if not found.

func (*ClaimsReport) IsPassing

func (r *ClaimsReport) IsPassing() bool

IsPassing returns true if the report passes validation.

func (*ClaimsReport) SetCriteria

func (r *ClaimsReport) SetCriteria(criteria ClaimsCriteria)

SetCriteria sets the validation criteria.

func (*ClaimsReport) ValidateDerivedClaims

func (r *ClaimsReport) ValidateDerivedClaims()

ValidateDerivedClaims checks that all derived claims reference verified source claims.

type ClaimsSummary

type ClaimsSummary struct {
	// Counts by verdict.
	Counts ClaimsCounts `json:"counts"`

	// ByCategory counts claims by category.
	ByCategory map[ClaimCategory]int `json:"byCategory,omitempty"`

	// BySourceType counts claims by validation source type.
	BySourceType map[SourceType]int `json:"bySourceType,omitempty"`

	// ByReliability counts external claims by reliability tier.
	ByReliability map[ReliabilityTier]int `json:"byReliability,omitempty"`

	// UnverifiedClaims lists IDs of unverified claims.
	UnverifiedClaims []string `json:"unverifiedClaims,omitempty"`

	// NeedsReviewClaims lists IDs of claims needing review.
	NeedsReviewClaims []string `json:"needsReviewClaims,omitempty"`

	// RejectedClaims lists IDs of rejected claims.
	RejectedClaims []string `json:"rejectedClaims,omitempty"`
}

ClaimsSummary provides aggregated statistics.

type DerivedValidation

type DerivedValidation struct {
	// SourceClaimIDs are the IDs of claims this is derived from.
	SourceClaimIDs []string `json:"sourceClaimIds"`

	// DerivationMethod describes how the claim was derived.
	DerivationMethod string `json:"derivationMethod"`

	// Formula is the calculation formula if applicable.
	Formula string `json:"formula,omitempty"`

	// Reasoning explains the derivation logic.
	Reasoning string `json:"reasoning,omitempty"`
}

DerivedValidation describes claims derived from other claims.

type ExternalSourceType

type ExternalSourceType string

ExternalSourceType categorizes the authority of external sources.

const (
	// ExternalNVD is the NIST National Vulnerability Database.
	ExternalNVD ExternalSourceType = "nvd"

	// ExternalVendorAdvisory is an official vendor advisory.
	ExternalVendorAdvisory ExternalSourceType = "vendor-advisory"

	// ExternalFramework is official framework documentation (MITRE, OWASP, CWE).
	ExternalFramework ExternalSourceType = "framework-official"

	// ExternalPeerReviewed is a peer-reviewed publication.
	ExternalPeerReviewed ExternalSourceType = "peer-reviewed"

	// ExternalReputableVendor is from a reputable vendor (e.g., research firms).
	ExternalReputableVendor ExternalSourceType = "reputable-vendor"

	// ExternalCommunity is from community sources (blogs, forums).
	ExternalCommunity ExternalSourceType = "community"

	// ExternalAPI is from a public API (e.g., FIRST.org EPSS API).
	ExternalAPI ExternalSourceType = "api"

	// ExternalAggregator is a third-party content-roundup or "stats blog" site
	// that reposts figures without independent reporting or a traceable
	// primary source (e.g. AI-generated SEO stats pages). Distinct from
	// ExternalCommunity: a community source (a named blog post, a forum
	// thread) is still someone's own account: an aggregator has no original
	// reporting to fall back on, so it defaults to auto-reject rather than
	// requires-review.
	ExternalAggregator ExternalSourceType = "aggregator"
)

type ExternalValidation

type ExternalValidation struct {
	// URL is the source URL.
	URL string `json:"url"`

	// SourceType categorizes the source.
	SourceType ExternalSourceType `json:"sourceType"`

	// Role distinguishes how directly this source speaks for the claim
	// (primary / secondary-relay / secondary-analysis / self-reported),
	// independent of SourceType's general authority category. Optional and
	// empty by default so existing claims are unaffected: an empty Role is
	// not flagged by RequiresCorroboration — only an explicitly-set
	// secondary-analysis or self-reported role is.
	Role SourceRole `json:"sourceRole,omitempty"`

	// Reliability indicates the trustworthiness of the source.
	Reliability ReliabilityTier `json:"reliability"`

	// AccessedAt is when the URL was accessed. Nil when unknown — a pointer
	// so omitempty actually omits it, rather than serializing the
	// time.Time zero value ("0001-01-01T00:00:00Z").
	AccessedAt *time.Time `json:"accessedAt,omitempty"`

	// Archived indicates if the URL is archived (e.g., Wayback Machine).
	Archived bool `json:"archived,omitempty"`

	// ArchiveURL is the archive URL if different from primary URL.
	ArchiveURL string `json:"archiveUrl,omitempty"`

	// QuotedText is the exact text from the source supporting the claim.
	QuotedText string `json:"quotedText,omitempty"`

	// VerifiedMatch indicates the claim text matches the source.
	VerifiedMatch bool `json:"verifiedMatch,omitempty"`
}

ExternalValidation describes validation via external source.

func (*ExternalValidation) WithAccessedAt added in v0.13.0

func (e *ExternalValidation) WithAccessedAt(t time.Time) *ExternalValidation

WithAccessedAt sets AccessedAt and returns the receiver for chaining.

type InternalValidation

type InternalValidation struct {
	// Method describes how validation was performed.
	Method InternalValidationMethod `json:"method"`

	// EvidencePath is the path to code, logs, or artifacts.
	EvidencePath string `json:"evidencePath,omitempty"`

	// EvidenceHash is a hash of the evidence file for integrity.
	EvidenceHash string `json:"evidenceHash,omitempty"`

	// Reproducible indicates whether the validation can be reproduced.
	Reproducible bool `json:"reproducible"`

	// ReproductionSteps describes how to reproduce the validation.
	ReproductionSteps string `json:"reproductionSteps,omitempty"`

	// ValidatedBy identifies who performed the validation.
	ValidatedBy string `json:"validatedBy,omitempty"`

	// ValidatedAt is when validation was performed. Nil when unknown — a
	// pointer so omitempty actually omits it, rather than serializing the
	// time.Time zero value ("0001-01-01T00:00:00Z").
	ValidatedAt *time.Time `json:"validatedAt,omitempty"`

	// Environment describes the validation environment.
	Environment *ValidationEnvironment `json:"environment,omitempty"`

	// Output is the observed output that validates the claim.
	Output string `json:"output,omitempty"`
}

InternalValidation describes validation via internal evidence.

func (*InternalValidation) WithValidatedAt added in v0.13.0

func (i *InternalValidation) WithValidatedAt(t time.Time) *InternalValidation

WithValidatedAt sets ValidatedAt and returns the receiver for chaining.

type InternalValidationMethod

type InternalValidationMethod string

InternalValidationMethod describes how internal validation was performed.

const (
	// MethodCodeExecution indicates the claim was validated by running code.
	MethodCodeExecution InternalValidationMethod = "code-execution"

	// MethodLabTesting indicates validation via controlled lab testing.
	MethodLabTesting InternalValidationMethod = "lab-testing"

	// MethodCodeReview indicates validation via code review/inspection.
	MethodCodeReview InternalValidationMethod = "code-review"

	// MethodLogAnalysis indicates validation via log analysis.
	MethodLogAnalysis InternalValidationMethod = "log-analysis"

	// MethodCalculation indicates the claim is a calculation from other data.
	MethodCalculation InternalValidationMethod = "calculation"

	// MethodObservation indicates direct observation of behavior.
	MethodObservation InternalValidationMethod = "observation"
)

type LintFinding added in v0.13.0

type LintFinding struct {
	ClaimID  string       `json:"claimId,omitempty"`
	Rule     string       `json:"rule"`
	Severity LintSeverity `json:"severity"`
	Message  string       `json:"message"`
}

LintFinding is a single problem found by Lint.

func Lint added in v0.13.0

func Lint(r *ClaimsReport) []LintFinding

Lint checks a claims report for evidence-integrity problems, centered on the invariant that a "verified" verdict must actually be backed by evidence: an external claim needs a resolving URL and a verbatim quote; a derived claim needs source claims; an internal claim needs evidence. The value-appears-in-quote check is advisory (a warning), because legitimate verified claims quote a rule rather than the number (e.g. a "0%" target) or a range, or scale the value into a unit ("20 million", "$60 billion").

A verified external claim whose SourceRole is secondary-analysis or self-reported (SourceRole.RequiresCorroboration) must carry at least one entry in RelatedClaimIDs — an independent corroborating claim — or Lint errors. An unset Role is not flagged, so existing reports that predate the Role field are unaffected.

Separately, if the report's own Criteria.MinCorroboratingSources is set (> 1), every verified claim in scope (all categories, or only Criteria.CorroborationCategories when set) must have at least that many independent sources (itself plus RelatedClaimIDs), regardless of validation type or SourceRole. Disabled by default (0), so existing reports are unaffected unless they opt in via Criteria.

Separately again, if the report's own Criteria.MaxClaimAge is set (> 0), every verified statistical claim's StatisticalDetail.AsOfDate must be within that duration of now, or Lint errors — a stat presented as current that describes a fact from years ago (e.g. a 2022 study cited as if it were still representative) is exactly the kind of quiet drift that erodes trust in a "verified" label over time. A claim with no Statistical detail, or an unset AsOfDate, is never flagged: age is unknown, not stale. Disabled by default (0), so existing reports are unaffected unless they opt in via Criteria.

Lint does not mutate the report. It complements DetermineVerdict: because a verdict can be hand-authored (bypassing DetermineVerdict), Lint re-checks that a stated "verified" is earned.

type LintSeverity added in v0.13.0

type LintSeverity string

LintSeverity classifies a lint finding.

const (
	// LintError is a finding that should block publication (non-zero exit).
	LintError LintSeverity = "error"

	// LintWarning is an advisory finding for human review.
	LintWarning LintSeverity = "warning"
)

type Location

type Location struct {
	// Section is the section heading or identifier.
	Section string `json:"section,omitempty"`

	// Line is the line number (1-indexed).
	Line int `json:"line,omitempty"`

	// StartOffset is the character offset from start of document.
	StartOffset int `json:"startOffset,omitempty"`

	// EndOffset is the ending character offset.
	EndOffset int `json:"endOffset,omitempty"`
}

Location identifies where a claim appears in a document.

type Precision added in v0.12.0

type Precision string

Precision indicates how exact a statistical claim's value is.

const (
	// PrecisionExact is a value stated exactly by the source (e.g. "4.7 million").
	PrecisionExact Precision = "exact"

	// PrecisionApproximate is a value the source itself qualifies as
	// approximate (e.g. "1M+", "~50%", "over 20,000").
	PrecisionApproximate Precision = "approximate"

	// PrecisionEstimated is a third-party or analyst estimate, not a figure
	// the primary source states directly.
	PrecisionEstimated Precision = "estimated"

	// PrecisionRange is a bounded range rather than a single point value
	// (e.g. "9.6 to 2.4 days"). Store the more notable end in Value and
	// describe the range in the claim Text.
	PrecisionRange Precision = "range"
)

type ReliabilityTier

type ReliabilityTier string

ReliabilityTier indicates the trustworthiness of a source.

const (
	// ReliabilityAuthoritative is an official, authoritative source (auto-accept).
	ReliabilityAuthoritative ReliabilityTier = "authoritative"

	// ReliabilityHigh is a highly reputable source (auto-accept).
	ReliabilityHigh ReliabilityTier = "high"

	// ReliabilityMedium is a moderately reputable source (requires review).
	ReliabilityMedium ReliabilityTier = "medium"

	// ReliabilityLow is an unverified or low-reputation source (reject).
	ReliabilityLow ReliabilityTier = "low"
)

func DefaultReliabilityForSourceType

func DefaultReliabilityForSourceType(st ExternalSourceType) ReliabilityTier

DefaultReliabilityForSourceType returns the default reliability tier for a source type.

func (ReliabilityTier) IsAcceptable

func (r ReliabilityTier) IsAcceptable() bool

IsAcceptable returns true if the reliability tier is acceptable without review.

func (ReliabilityTier) RequiresReview

func (r ReliabilityTier) RequiresReview() bool

RequiresReview returns true if the reliability tier requires human review.

type SourceRole added in v0.13.0

type SourceRole string

SourceRole distinguishes how directly an external source speaks for the claim, independent of ExternalSourceType (which is about the source's general authority/category). Two "reputable-vendor" sources can carry very different trust: a wire report quoting an earnings call verbatim is SourceRolePrimary-adjacent; an outlet's own synthesis across several other reports is SourceRoleSecondaryAnalysis and is exactly the shape that produced a false-positive "verified" figure ($3B ARR from a secondary synthesis, contradicted by the primary source's own $500M figure) — the incident that motivated this field.

const (
	// SourceRolePrimary is the entity the claim is about, speaking for
	// itself (a company blog post, an official filing, a direct quote from
	// an executive).
	SourceRolePrimary SourceRole = "primary"

	// SourceRoleSecondaryRelay is a reputable outlet directly reporting a
	// primary statement (e.g. a wire service relaying an earnings-call
	// quote) — one hop from primary, with low synthesis risk.
	SourceRoleSecondaryRelay SourceRole = "secondary-relay"

	// SourceRoleSecondaryAnalysis is an outlet's own synthesis, estimate, or
	// aggregation across multiple other reports — not a direct relay of a
	// single primary statement. Higher risk of drift from the underlying
	// fact; requires corroboration to be published as verified.
	SourceRoleSecondaryAnalysis SourceRole = "secondary-analysis"

	// SourceRoleSelfReported is the claim's subject describing itself in a
	// context with a promotional incentive (marketing page, press release
	// superlative) rather than an audited disclosure. Requires
	// corroboration to be published as verified.
	SourceRoleSelfReported SourceRole = "self-reported"
)

func (SourceRole) RequiresCorroboration added in v0.13.0

func (r SourceRole) RequiresCorroboration() bool

RequiresCorroboration reports whether a claim sourced with this role needs at least one independent corroborating source before it can be published as verified. Primary and secondary-relay sources speak for themselves; secondary-analysis and self-reported sources carry synthesis or incentive risk that a second independent source mitigates.

type SourceType

type SourceType string

SourceType identifies how a claim is validated.

const (
	// SourceExternal indicates validation via external URL reference.
	SourceExternal SourceType = "external"

	// SourceInternal indicates validation via internal evidence (code, lab tests).
	SourceInternal SourceType = "internal"

	// SourceDerived indicates the claim is calculated from other validated claims.
	SourceDerived SourceType = "derived"

	// SourceSubjective indicates an estimate without objective backing.
	SourceSubjective SourceType = "subjective"
)

type StatisticalDetail added in v0.12.0

type StatisticalDetail struct {
	// Value is the numeric value of the claim.
	Value float64 `json:"value"`

	// Unit is the unit of measurement (e.g. "%", "USD", "users"). Empty for
	// dimensionless counts.
	Unit string `json:"unit,omitempty"`

	// Precision indicates how exact the value is.
	Precision Precision `json:"precision,omitempty"`

	// AsOfDate is when the underlying fact was true, if known and different
	// from when the source was accessed.
	AsOfDate *time.Time `json:"asOfDate,omitempty"`
}

StatisticalDetail captures the structured numeric value behind a ClaimStatistical claim. It is kept separate from Claim.Text (which remains the free-text rendering, e.g. "4.7M paid subscribers") so the number itself is queryable and can be checked against ExternalValidation.QuotedText programmatically, instead of only existing inside a formatted string.

AsOfDate is distinct from ExternalValidation.AccessedAt: AccessedAt is when the source URL was crawled; AsOfDate is when the underlying fact was true (e.g. the earnings period the figure describes, or the date a public statement was made). Case-study and market-signal claims routinely need both — a stat crawled today can describe a fact from months earlier.

func NewStatisticalDetail added in v0.12.0

func NewStatisticalDetail(value float64, unit string, precision Precision) *StatisticalDetail

NewStatisticalDetail creates a StatisticalDetail with the given value, unit, and precision. Set AsOfDate directly on the result if known.

func (*StatisticalDetail) WithAsOfDate added in v0.12.0

func (d *StatisticalDetail) WithAsOfDate(t time.Time) *StatisticalDetail

WithAsOfDate sets AsOfDate and returns the receiver for chaining.

type SubjectiveRecommendation

type SubjectiveRecommendation string

SubjectiveRecommendation indicates what to do with a subjective claim.

const (
	// RecommendKeepWithDisclaimer keeps the claim with a disclaimer.
	RecommendKeepWithDisclaimer SubjectiveRecommendation = "keep-with-disclaimer"

	// RecommendRemove removes the claim.
	RecommendRemove SubjectiveRecommendation = "remove"

	// RecommendFindSource suggests finding an external source.
	RecommendFindSource SubjectiveRecommendation = "find-source"

	// RecommendConvertToInternal suggests validating internally.
	RecommendConvertToInternal SubjectiveRecommendation = "convert-to-internal"
)

type SubjectiveValidation

type SubjectiveValidation struct {
	// Acknowledged indicates if this is labeled as an estimate in the document.
	Acknowledged bool `json:"acknowledged"`

	// Methodology describes any methodology used for the estimate.
	Methodology string `json:"methodology,omitempty"`

	// Recommendation suggests what to do with this claim.
	Recommendation SubjectiveRecommendation `json:"recommendation"`

	// Rationale explains why this is acceptable or not.
	Rationale string `json:"rationale,omitempty"`
}

SubjectiveValidation describes subjective estimates.

type Validation

type Validation struct {
	// Type indicates the validation approach.
	Type SourceType `json:"type"`

	// External contains details for externally-sourced claims.
	External *ExternalValidation `json:"external,omitempty"`

	// Internal contains details for internally-validated claims.
	Internal *InternalValidation `json:"internal,omitempty"`

	// Derived contains details for claims derived from other claims.
	Derived *DerivedValidation `json:"derived,omitempty"`

	// Subjective contains details for subjective estimates.
	Subjective *SubjectiveValidation `json:"subjective,omitempty"`
}

Validation describes how a claim is validated. Exactly one of External, Internal, Derived, or Subjective should be set.

func NewDerivedValidation

func NewDerivedValidation(sourceClaimIDs []string, method, formula string) *Validation

NewDerivedValidation creates a validation for a derived claim.

func NewExternalValidation

func NewExternalValidation(url string, sourceType ExternalSourceType) *Validation

NewExternalValidation creates a validation for an external source.

func NewInternalValidation

func NewInternalValidation(method InternalValidationMethod, evidencePath string, reproducible bool) *Validation

NewInternalValidation creates a validation for internal evidence.

func NewSubjectiveValidation

func NewSubjectiveValidation(acknowledged bool, recommendation SubjectiveRecommendation) *Validation

NewSubjectiveValidation creates a validation for a subjective estimate.

type ValidationEnvironment

type ValidationEnvironment struct {
	// Product is the product being tested.
	Product string `json:"product,omitempty"`

	// Version is the version tested.
	Version string `json:"version,omitempty"`

	// Configuration describes the configuration used.
	Configuration string `json:"configuration,omitempty"`

	// Platform is the platform (os, arch).
	Platform string `json:"platform,omitempty"`
}

ValidationEnvironment describes the environment where validation occurred.

type Verdict

type Verdict string

Verdict represents the validation result for a claim.

const (
	// VerdictVerified indicates the claim is verified.
	VerdictVerified Verdict = "verified"

	// VerdictUnverified indicates the claim could not be verified.
	VerdictUnverified Verdict = "unverified"

	// VerdictNeedsReview indicates the claim requires human review.
	VerdictNeedsReview Verdict = "needs-review"

	// VerdictRejected indicates the claim should be removed.
	VerdictRejected Verdict = "rejected"
)

func DetermineVerdict

func DetermineVerdict(v *Validation) Verdict

DetermineVerdict computes the verdict based on validation.

func (Verdict) Icon

func (v Verdict) Icon() string

Icon returns the emoji icon for the verdict.

func (Verdict) IsBlocking

func (v Verdict) IsBlocking() bool

IsBlocking returns true if the verdict blocks publication.

func (Verdict) IsPassing

func (v Verdict) IsPassing() bool

IsPassing returns true if the verdict is acceptable for publication.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL