Skip to content

Interpreting Refract output

Refract emits a deterministic event stream. This page explains how to read it.

Every event has the same structure. This one is from refract export "Bitcoin" --from 369361755 --to 369393212 --format ndjson:

{
"eventType": "citation_removed",
"fromRevisionId": 369361755,
"toRevisionId": 369393212,
"section": "Basis of Value",
"before": "<ref>[http://www.bitcoin.org/faq Bitcoin FAQ]</ref>",
"after": "",
"deterministicFacts": [
{ "fact": "citation_changed", "detail": "type=removed" }
],
"layer": "observed",
"timestamp": "2010-06-21T17:29:07Z",
"schemaVersion": "0.5.0",
"editMagnitude": "minor",
"contentChange": "compression",
"keyTerms": ["bitcoin"],
"certaintyProfile": { "high": 0, "medium": 0, "low": 0, "hedging": 0 },
"directionSignal": "neutral",
"quantitativeFindings": [],
"eventId": "614217608b4726d4"
}

eventId is added by refract export; refract analyze --json prints the same event without it. Neither command writes a claimId on events.

Field What it tells you
eventType Kind of change — sentence, citation, template, revert, section, etc. See event taxonomy.
fromRevisionId / toRevisionId The revision boundary where this change occurred. from is the parent revision; to is the revision containing the change. On talk_page_correlated, from is the article revision and to is the talk page revision nearest to it in time.
section Which section the change belongs to. (lead) means the page introduction. Not all event types use this field.
before / after The text before and after the change. For additions, before is empty. For removals, after is empty. For modifications, both are present. At --depth brief both are empty on almost every event. On revert_detected, after holds the edit summary that matched and before is empty.
deterministicFacts Why the engine produced this event. Always mechanical — pure functions of the wikitext. Each fact has a fact name and a detail string. The schema allows an optional provenance object; the CLI does not fill it.
layer Where the evidence came from: "observed" (deterministic), "policy_coded" (rules-based), "model_interpretation" (downstream only), "speculative" (low confidence), "unknown".
schemaVersion Which schema version produced this event. Use this for compatibility checks when consuming events across package versions.

These events track propositional content across revisions. A sentence is identified by its text; Refract detects when the same sentence appears, disappears, changes, or returns.

Claim lifecycle across revisions

  • sentence_first_seen: This text has never appeared before in the revision range.
  • sentence_removed: This text was present in the previous revision and is absent now.
  • sentence_modified: The text changed but is similar enough (above the similarity threshold) to be considered the same sentence.
  • sentence_reintroduced: Text that was previously removed has returned.

Citations are extracted from <ref> tags in wikitext.

  • citation_added: A new reference was added.
  • citation_removed: An existing reference was deleted.
  • citation_replaced: One reference was swapped for another at the same position.

Templates like {{citation needed}}, {{NPOV}}, {{BLP sources}} are Wikipedia's dispute signals. Refract tracks them mechanically.

  • template_added: A template was inserted into the page.
  • template_removed: A template was taken out.
  • template_parameter_changed: A template's parameters were modified (e.g., date updated on a maintenance tag).

Structural changes (section_*, lead_*, page_moved)

Section titled “Structural changes (section_*, lead_*, page_moved)”
  • section_reorganized: Sections were added, removed, or reordered.
  • lead_promotion: Content was moved from the body into the lead section.
  • lead_demotion: Content was moved from the lead into the body.
  • page_moved: The entire page was renamed.

Dispute signals (revert_*, edit_cluster_*)

Section titled “Dispute signals (revert_*, edit_cluster_*)”
  • revert_detected: An edit was reverted, detected from the edit summary matching revert patterns. Its section is empty.
  • edit_cluster_detected: Multiple edits occurred within a tight time window (default: 3+ edits in 1 hour; --cluster-window changes it). The event spans the cluster, from its first revision to its last, and its section is empty.

These events correlate article revisions with their associated talk pages. refract analyze and refract export emit all five from the ten talk-page edits that precede the last analyzed revision. Thread events cover the talk edits made since the first analyzed revision.

  • talk_page_correlated: An article revision has a nearby talk page revision.
  • talk_thread_opened: A new discussion thread was started.
  • talk_thread_archived: A thread was closed or archived.
  • talk_reply_added: A reply was posted in an existing thread.
  • talk_activity_spike: Talk page activity on one day exceeded the threshold (default: 3× the moving average; --spike-factor changes it). The CLI looks for spikes among the ten talk-page edits that precede the last analyzed revision, within the seven days before it, so most runs emit none.

A claim that has sentence_first_seen early in the timeline, no sentence_modified events, and is still present at the end of the revision range is stable.

A claim with frequent sentence_modified events, revert_detected in its section, and template_added with dispute templates ({{NPOV}}, {{citation needed}}) is actively contested.

A citation that was added and then removed within a short revision window (or was replaced multiple times) is source-fragile — the page's evidence base for that claim is unstable.

category_removed immediately followed by category_added with a different category in the same revision boundary is a canon reclassification. sentence_removed on a long-standing claim followed by sentence_first_seen with different text in the same section is a retcon.

When building on Refract's event stream:

  1. Filter by eventType to isolate the signal you care about (e.g., citation events for source churn analysis).
  2. Group by section to find which parts of the page are most active.
  3. Follow one passage with refract claim, or group the claims in refract analyze --report, which assigns each a claimId. Events themselves carry no claimId.
  4. Sort by timestamp to reconstruct the chronological sequence.
  5. Never interpret layer values you didn't set — model_interpretation is for downstream use only. Refract never sets it.

The event stream is pure NDJSON — pipe it, filter it, join it, archive it.