Strategic context
Viral religious content consistently uses two fabrication patterns that are categorically distinct from existing proof-text-guards coverage:
-
Misquoted canonical verses — a real verse cited with words that are not in the verse. Recent example: "Proverbs 3:13: Blessed are those who seek wisdom, for they will not be deceived. Blessed are those who know the enemy, for they will escape his snares." Proverbs 3:13 actually reads "Blessed are those who find wisdom, those who gain understanding" (NIV) — the rest is fabricated.
-
Misattributed extrabiblical quotations — words attributed to 1 Enoch / Jasher / Gospel of Thomas / Dead Sea Scrolls that do not appear in any extant text. Recent example: "Enoch wrote: They will lead many astray, and the truth will be hidden from the children of men." Not present in 1 Enoch (Ge'ez, Aramaic, or Greek).
proof-text-guards.json covers real verses misapplied through reading. It does not cover fabricated wording or false attribution. The schemas differ enough that conflation would erode the proof-text-guards entries' usefulness.
This card adds a new content type — false-citations — with the schema, two seed entries, build-pipeline wiring, and a SQLite landing table.
Parent epic: #1536
Related cards: #1817, #1819, #1820, #1821 (Divine Council / cosmic-conflict content) — those cards may want to cross-reference false-citations entries
Deliverables
- New metadata file:
content/meta/false-citations.json
- Two seed entries: misquoted Proverbs 3:13; pseudo-Enoch "children of men"
- Schema-validator coverage in
_tools/schema_validator.py
- SQLite loader in
_tools/build_sqlite_loaders.py + table DDL in _tools/build_sqlite_schema.py
- SQLite validator check in
_tools/validate_sqlite.py
All deliverables ship in the same PR.
Deliverable 1 — Schema
File created: content/meta/false-citations.json
Top-level type: JSON array (match difficult-passages.json and proof-text-guards.json convention).
Entry schema:
Schema rules:
id must be unique across the file
category enum strict; reject any other value
claimed_source_* fields all required to be either populated or null together (no partial population)
actual_text_* fields all required to be either populated or null together
- If
status == "fabricated", actual_text and all actual_text_* MUST be null
- If
status == "misquoted", actual_text MUST be populated
- If
status == "misattributed", actual_text is typically null but may be populated if the misattribution swaps a real quote between sources
Deliverable 2 — Seed entries
Entry 1 — fabricated Proverbs 3:13
{
"id": "proverbs-3-13-seek-wisdom-deceived",
"category": "misquoted-canonical",
"alleged_text": "Blessed are those who seek wisdom, for they will not be deceived. Blessed are those who know the enemy, for they will escape his snares.",
"claimed_source": "Proverbs 3:13",
"claimed_source_book_id": "proverbs",
"claimed_source_chapter": 3,
"claimed_source_verse": 13,
"status": "misquoted",
"actual_text": "Blessed are those who find wisdom, those who gain understanding.",
"actual_text_translation": "NIV",
"actual_text_book_id": "proverbs",
"actual_text_chapter": 3,
"actual_text_verse": 13,
"what_is_wrong": "Proverbs 3:13 commends finding wisdom and gaining understanding. It does not contain the words 'deceived,' 'enemy,' or 'snares.' The circulating wording appears to be a free composition styled to fit conspiracy-adjacent content.",
"why_it_circulates": "The fabricated wording functions rhetorically — it lets a viral post close on a 'biblical' note that endorses the post's framing about hidden truth and enemies. Readers who have not opened a Bible to Proverbs 3 in some time will not catch the swap.",
"related_difficult_passage_ids": [],
"tags": ["fabricated", "viral-content", "wisdom-literature"]
}
Entry 2 — pseudo-Enoch
{
"id": "pseudo-enoch-children-of-men",
"category": "misattributed-extrabiblical",
"alleged_text": "They will lead many astray, and the truth will be hidden from the children of men.",
"claimed_source": "Book of Enoch",
"claimed_source_book_id": null,
"claimed_source_chapter": null,
"claimed_source_verse": null,
"status": "fabricated",
"actual_text": null,
"actual_text_translation": null,
"actual_text_book_id": null,
"actual_text_chapter": null,
"actual_text_verse": null,
"what_is_wrong": "These words do not appear in any extant text of 1 Enoch — neither in the Ge'ez full text, the Aramaic Qumran fragments (4QEn^a-g), nor the Greek fragments (Codex Panopolitanus, Chester Beatty). 1 Enoch's actual treatment of the Watchers' end (1 En. 10, 16) describes their binding and the judgment of their offspring's spirits, not their continuing rule over humanity.",
"why_it_circulates": "The line is styled to sound like 1 Enoch — biblical cadence, 'children of men' phrasing, generic apocalyptic warning. It lets a viral post claim Enoch endorses a hidden-truth / leading-astray framing the actual text does not support. Few readers can verify against the real Ge'ez or Aramaic text.",
"related_difficult_passage_ids": ["jude-quotes-enoch", "ethiopian-bible-true-canon"],
"tags": ["fabricated", "viral-content", "extrabiblical", "1-enoch"]
}
Deliverable 3 — Schema validator
File modified: _tools/schema_validator.py
Add a validate_false_citations() function following the existing pattern (modelled on the closest existing validator — likely validate_difficult_passages or validate_proof_text_guards). Enforce:
- File parses as JSON array
- Each entry has required fields per the schema above
id values are unique
category and status enum values are valid
- The conditional-population rules:
claimed_source_* fields populated-together-or-all-null; same for actual_text_*
status == "fabricated" ⇒ actual_text is null
status == "misquoted" ⇒ actual_text is non-null
claimed_source_book_id, when non-null, resolves in books.json
actual_text_book_id, when non-null, resolves in books.json
- All
related_difficult_passage_ids resolve in difficult-passages.json
- All
tags are non-empty strings
Add the validator to the main validation runner so it executes by default.
Deliverable 4 — SQLite loader and schema
Files modified: _tools/build_sqlite_loaders.py, _tools/build_sqlite_schema.py
Table DDL (in build_sqlite_schema.py):
CREATE TABLE IF NOT EXISTS false_citations (
id TEXT PRIMARY KEY,
category TEXT NOT NULL,
alleged_text TEXT NOT NULL,
claimed_source TEXT NOT NULL,
claimed_source_book_id TEXT,
claimed_source_chapter INTEGER,
claimed_source_verse INTEGER,
status TEXT NOT NULL,
actual_text TEXT,
actual_text_translation TEXT,
actual_text_book_id TEXT,
actual_text_chapter INTEGER,
actual_text_verse INTEGER,
what_is_wrong TEXT NOT NULL,
why_it_circulates TEXT NOT NULL,
tags_json TEXT
);
CREATE TABLE IF NOT EXISTS false_citation_related (
false_citation_id TEXT NOT NULL REFERENCES false_citations(id),
difficult_passage_id TEXT NOT NULL,
PRIMARY KEY (false_citation_id, difficult_passage_id)
);
CREATE INDEX IF NOT EXISTS idx_false_citations_status ON false_citations(status);
CREATE INDEX IF NOT EXISTS idx_false_citations_book ON false_citations(claimed_source_book_id);
Loader (in build_sqlite_loaders.py):
- Add
load_false_citations(conn, content_root) following the pattern of existing loaders (load_difficult_passages is the closest precedent)
- Reads
content/meta/false-citations.json
- Inserts one row per entry into
false_citations
- Serialises
tags as JSON into tags_json
- Inserts one row per
related_difficult_passage_ids element into false_citation_related
- Wire the new loader into the main pipeline in
build_sqlite.py
Deliverable 5 — SQLite validator
File modified: _tools/validate_sqlite.py
Add an integrity check that:
false_citations table exists and has the expected column set
- All rows in
false_citation_related.difficult_passage_id resolve to a row in difficult_passages (assuming that table name — verify against existing loader output)
- Both seed entries are present after build
Acceptance criteria
Out of scope
- App-side UI rendering for
false_citations — separate card once content density justifies it (after we have ~10 entries, this surfaces as a "How to spot fabricated citations" Explore card; that is a future deliverable, not this one)
- Bulk-seeding additional false-citation entries — this card establishes the infrastructure and two seeds; subsequent enrichment is its own backlog
- Cross-linking from app screens (chapter views, panels) into false-citations — separate cards once the table is populated
Future cards this enables
Once this infrastructure ships, the following become small (XS) content-only cards:
- Pseudo-Jasher quotes (multiple in circulation)
- Misquoted Jeremiah 1:5 ("I knew you in your mother's womb" — actual: "Before I formed you in the womb I knew you")
- Pseudo-Gospel of Thomas sayings used in spiritual-but-not-religious content
- Misattributed C. S. Lewis / Bonhoeffer / Spurgeon quotations (out-of-canon but a known pattern)
Each subsequent entry uses the schema established here without further infrastructure work.
Strategic context
Viral religious content consistently uses two fabrication patterns that are categorically distinct from existing
proof-text-guardscoverage:Misquoted canonical verses — a real verse cited with words that are not in the verse. Recent example: "Proverbs 3:13: Blessed are those who seek wisdom, for they will not be deceived. Blessed are those who know the enemy, for they will escape his snares." Proverbs 3:13 actually reads "Blessed are those who find wisdom, those who gain understanding" (NIV) — the rest is fabricated.
Misattributed extrabiblical quotations — words attributed to 1 Enoch / Jasher / Gospel of Thomas / Dead Sea Scrolls that do not appear in any extant text. Recent example: "Enoch wrote: They will lead many astray, and the truth will be hidden from the children of men." Not present in 1 Enoch (Ge'ez, Aramaic, or Greek).
proof-text-guards.jsoncovers real verses misapplied through reading. It does not cover fabricated wording or false attribution. The schemas differ enough that conflation would erode the proof-text-guards entries' usefulness.This card adds a new content type —
false-citations— with the schema, two seed entries, build-pipeline wiring, and a SQLite landing table.Parent epic: #1536
Related cards: #1817, #1819, #1820, #1821 (Divine Council / cosmic-conflict content) — those cards may want to cross-reference
false-citationsentriesDeliverables
content/meta/false-citations.json_tools/schema_validator.py_tools/build_sqlite_loaders.py+ table DDL in_tools/build_sqlite_schema.py_tools/validate_sqlite.pyAll deliverables ship in the same PR.
Deliverable 1 — Schema
File created:
content/meta/false-citations.jsonTop-level type: JSON array (match
difficult-passages.jsonandproof-text-guards.jsonconvention).Entry schema:
{ "id": "string-kebab-case", // unique, required "category": "misquoted-canonical | misattributed-extrabiblical | fabricated-no-source", "alleged_text": "the wording as it circulates", // required "claimed_source": "human-readable source string", // e.g. "Proverbs 3:13" or "1 Enoch" "claimed_source_book_id": "proverbs | null", // null for non-canonical sources "claimed_source_chapter": 3, // null if not applicable "claimed_source_verse": 13, // null if not applicable "status": "fabricated | misquoted | misattributed", "actual_text": "the real verse, or null if no source exists", // null for fabricated "actual_text_translation": "NIV | ESV | original", "actual_text_book_id": "proverbs | null", "actual_text_chapter": 3, "actual_text_verse": 13, "what_is_wrong": "1-3 sentence explanation", // required "why_it_circulates": "1-3 sentence pastoral note", // required, charitable framing "related_difficult_passage_ids": ["ethiopian-bible-true-canon"], // optional cross-refs "tags": ["string"] // optional }Schema rules:
idmust be unique across the filecategoryenum strict; reject any other valueclaimed_source_*fields all required to be either populated or null together (no partial population)actual_text_*fields all required to be either populated or null togetherstatus == "fabricated",actual_textand allactual_text_*MUST be nullstatus == "misquoted",actual_textMUST be populatedstatus == "misattributed",actual_textis typically null but may be populated if the misattribution swaps a real quote between sourcesDeliverable 2 — Seed entries
Entry 1 — fabricated Proverbs 3:13
{ "id": "proverbs-3-13-seek-wisdom-deceived", "category": "misquoted-canonical", "alleged_text": "Blessed are those who seek wisdom, for they will not be deceived. Blessed are those who know the enemy, for they will escape his snares.", "claimed_source": "Proverbs 3:13", "claimed_source_book_id": "proverbs", "claimed_source_chapter": 3, "claimed_source_verse": 13, "status": "misquoted", "actual_text": "Blessed are those who find wisdom, those who gain understanding.", "actual_text_translation": "NIV", "actual_text_book_id": "proverbs", "actual_text_chapter": 3, "actual_text_verse": 13, "what_is_wrong": "Proverbs 3:13 commends finding wisdom and gaining understanding. It does not contain the words 'deceived,' 'enemy,' or 'snares.' The circulating wording appears to be a free composition styled to fit conspiracy-adjacent content.", "why_it_circulates": "The fabricated wording functions rhetorically — it lets a viral post close on a 'biblical' note that endorses the post's framing about hidden truth and enemies. Readers who have not opened a Bible to Proverbs 3 in some time will not catch the swap.", "related_difficult_passage_ids": [], "tags": ["fabricated", "viral-content", "wisdom-literature"] }Entry 2 — pseudo-Enoch
{ "id": "pseudo-enoch-children-of-men", "category": "misattributed-extrabiblical", "alleged_text": "They will lead many astray, and the truth will be hidden from the children of men.", "claimed_source": "Book of Enoch", "claimed_source_book_id": null, "claimed_source_chapter": null, "claimed_source_verse": null, "status": "fabricated", "actual_text": null, "actual_text_translation": null, "actual_text_book_id": null, "actual_text_chapter": null, "actual_text_verse": null, "what_is_wrong": "These words do not appear in any extant text of 1 Enoch — neither in the Ge'ez full text, the Aramaic Qumran fragments (4QEn^a-g), nor the Greek fragments (Codex Panopolitanus, Chester Beatty). 1 Enoch's actual treatment of the Watchers' end (1 En. 10, 16) describes their binding and the judgment of their offspring's spirits, not their continuing rule over humanity.", "why_it_circulates": "The line is styled to sound like 1 Enoch — biblical cadence, 'children of men' phrasing, generic apocalyptic warning. It lets a viral post claim Enoch endorses a hidden-truth / leading-astray framing the actual text does not support. Few readers can verify against the real Ge'ez or Aramaic text.", "related_difficult_passage_ids": ["jude-quotes-enoch", "ethiopian-bible-true-canon"], "tags": ["fabricated", "viral-content", "extrabiblical", "1-enoch"] }Deliverable 3 — Schema validator
File modified:
_tools/schema_validator.pyAdd a
validate_false_citations()function following the existing pattern (modelled on the closest existing validator — likelyvalidate_difficult_passagesorvalidate_proof_text_guards). Enforce:idvalues are uniquecategoryandstatusenum values are validclaimed_source_*fields populated-together-or-all-null; same foractual_text_*status == "fabricated"⇒actual_textis nullstatus == "misquoted"⇒actual_textis non-nullclaimed_source_book_id, when non-null, resolves inbooks.jsonactual_text_book_id, when non-null, resolves inbooks.jsonrelated_difficult_passage_idsresolve indifficult-passages.jsontagsare non-empty stringsAdd the validator to the main validation runner so it executes by default.
Deliverable 4 — SQLite loader and schema
Files modified:
_tools/build_sqlite_loaders.py,_tools/build_sqlite_schema.pyTable DDL (in
build_sqlite_schema.py):Loader (in
build_sqlite_loaders.py):load_false_citations(conn, content_root)following the pattern of existing loaders (load_difficult_passagesis the closest precedent)content/meta/false-citations.jsonfalse_citationstagsas JSON intotags_jsonrelated_difficult_passage_idselement intofalse_citation_relatedbuild_sqlite.pyDeliverable 5 — SQLite validator
File modified:
_tools/validate_sqlite.pyAdd an integrity check that:
false_citationstable exists and has the expected column setfalse_citation_related.difficult_passage_idresolve to a row indifficult_passages(assuming that table name — verify against existing loader output)Acceptance criteria
content/meta/false-citations.jsonexists with the two seed entriesschema_validator.pyruns clean against the fileschema_validator.pyrejects deliberately-broken test cases (verify by running locally with a temporary invalid entry — do not commit the broken case)build_sqlite.pyruns clean;false_citationstable populated with 2 rows;false_citation_relatedtable populated with 1 row (from the pseudo-Enoch entry's cross-refs)validate_sqlite.pypasses including the new integrity checkproof-text-guards) for future-Craig-reading-the-archaeologyOut of scope
false_citations— separate card once content density justifies it (after we have ~10 entries, this surfaces as a "How to spot fabricated citations" Explore card; that is a future deliverable, not this one)Future cards this enables
Once this infrastructure ships, the following become small (XS) content-only cards:
Each subsequent entry uses the schema established here without further infrastructure work.