"""Check a drafted legal document for the Four-Filter house rule: any
superlative or absolute-motive language ("willful", "egregious", "always",
"never", ...) must sit next to a supporting fact — an exhibit reference, a
dated fact, a [CITATION NEEDED]/[SOURCE] tag, or another specific factual
detail in the same sentence or paragraph. Unsupported superlatives are the
classic Defamation/Perjury filter failure: a claim about the other side's
state of mind or an absolute pattern that the drafter cannot actually prove.
This does not replace human judgment on the full Four-Filter check (Factual,
Defamation, Perjury, Admission) — it enforces the mechanically checkable
slice: superlative/absolute language paired with a supporting fact.
Usage: check_four_filter.py <document.md> [<document2.md> ...]
Exit 0 = every flagged term has a nearby supporting fact.
Exit 1 = at least one occurrence has no nearby supporting fact.
Exit 2 = usage/file error.
# Superlative / absolute-motive words that make a factual or state-of-mind
# claim stronger than plain narration. This list is necessarily incomplete —
# extend it as new patterns show up in review. Matched case-insensitively,
# word-boundary bounded so "reckless" doesn't also match "recklessness"-only
# false positives (it will match both, which is fine — both need support).
"willful", "willfully", "wilful", "egregious", "egregiously",
"always", "never", "flagrant", "flagrantly", "malicious", "maliciously",
"intentionally", "deliberately", "deliberate", "outrageous", "outrageously",
"reckless", "recklessly", "fraudulent", "fraudulently", "blatant", "blatantly",
"systematic", "systematically", "relentless", "relentlessly",
"callous", "callously", "unconscionable", "vindictive", "vindictively",
"premeditated", "knowingly", "in bad faith", "bad-faith",
# Signals that count as "a supporting fact nearby": exhibit refs, dated facts,
# explicit sourcing tags, invoice/case/paragraph numbers, or dollar amounts.
r"\bExhibit\s+[A-Z0-9]+\b",
r"\b\d{4}-\d{2}-\d{2}\b", # ISO date
r"\b(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|"
r"Jul(?:y)?|Aug(?:ust)?|Sep(?:tember)?|Oct(?:ober)?|Nov(?:ember)?|"
r"Dec(?:ember)?)\.?\s+\d{1,2},?\s+\d{4}\b", # "March 15, 2026"
r"\$[\d,]+(?:\.\d{2})?", # dollar amount
r"\bsee\s+(?:supra|infra)\b",
r"\b(?:invoice|email|letter|receipt|contract|order)\s+(?:dated|no\.|#)\s*\S+",
SUPPORT_RE = re.compile("|".join(SUPPORT_PATTERNS), re.IGNORECASE)
r"\b(" + "|".join(re.escape(w) for w in SUPERLATIVES) + r")\b",
# How far around the term (in characters) counts as "same sentence/paragraph".
def paragraph_bounds(text: str, pos: int) -> tuple[int, int]:
"""Return the start/end offsets of the blank-line-delimited paragraph
containing pos, so support anywhere in the paragraph counts."""
start = text.rfind("\n\n", 0, pos)
start = 0 if start == -1 else start + 2
end = text.find("\n\n", pos)
end = len(text) if end == -1 else end
def check_file(path: str) -> int:
text = open(path, encoding="utf-8").read()
print(f"ERROR: cannot read {path}: {e}", file=sys.stderr)
for m in TERM_RE.finditer(text):
p_start, p_end = paragraph_bounds(text, m.start())
w_start = max(p_start, m.start() - WINDOW)
w_end = min(p_end, m.end() + WINDOW)
window_text = text[w_start:w_end]
if not SUPPORT_RE.search(window_text):
line = text.count("\n", 0, m.start()) + 1
print(f"{path}:{line}: '{m.group(1)}' has no nearby supporting "
f"fact (exhibit, dated fact, dollar amount, or "
f"[CITATION NEEDED]/[SOURCE]/[VERIFY] tag)")
print("Usage: check_four_filter.py <document.md> [<document2.md> ...]",
for path in sys.argv[1:]:
result = check_file(path)
worst = max(worst, result)
print("✅ every superlative/absolute term has a nearby supporting fact")
if __name__ == "__main__":