"""Check a drafted legal document for the two non-negotiable safety rules:
every citation-shaped string is either real-looking or explicitly flagged with
[VERIFY] (drafter convention) or [FILL IN: ...] / [VERIFY: ...] (template
convention), and the attorney-review disclaimer block is present verbatim.
Usage: check_legal_doc.py <document.md> [<document2.md> ...]
# Tier 1 — fully recognized reporters: federal, Virginia, California, New York.
# These are specific, well-known citation shapes we can match with confidence.
CITATION_SHAPE = re.compile(
r"U\.?S\.?C?\.?|F\.\d?d|S\.\s?Ct\.|" # federal
r"Va\.\s?(?:App\.|Code)?|" # Virginia
r"Cal\.\s?(?:App\.\s?\d?d?|Rptr\.\s?\d?d?|)|" # California
r"N\.Y\.(?:2d|3d|S\.2d|S\.3d)?" # New York
r")\s*(?:§|Ann\.)?\s*\d+"
# Tier 2 — generic fallback: "Word. 123" shaped strings (other state reporters,
# e.g. "Mass. App. 456", "Ill. 2d 789"). WEAKER / UNVERIFIED tier: it only
# confirms the string LOOKS like a reporter citation, not that the reporter
# abbreviation is real or that the citation itself is real. Never report a
# generic-tier match as equivalent to a Tier 1 (federal/VA/CA/NY) match.
CITATION_SHAPE_GENERIC = re.compile(
r"\b[A-Z][a-z]+\.\s+\d+\b"
DISCLAIMER_MARKERS = ("does not constitute legal advice", "consult a licensed attorney", "attorney review")
def _is_marked(text: str, start: int, end: int) -> bool:
window = text[end:end + 40]
before = text[max(0, start - 40):start]
# Accept either [VERIFY] (drafter convention) or [FILL IN:]/[VERIFY:] (template convention)
re.search(r"\[VERIFY\]|\[FILL IN|\[VERIFY", window)
or re.search(r"\[VERIFY\]|\[FILL IN|\[VERIFY", before)
def check_file(path: str) -> int:
text = open(path, encoding="utf-8").read()
tier1_matches = list(CITATION_SHAPE.finditer(text))
tier1_spans = [(m.start(), m.end()) for m in tier1_matches]
1 for m in tier1_matches if not _is_marked(text, m.start(), m.end())
if tier1_matches and unflagged_tier1:
print(f"❌ {unflagged_tier1} citation-shaped string(s) (federal/VA/CA/NY) with no nearby marker ([VERIFY], [FILL IN: ...], or [VERIFY: ...])")
print(f"✅ all {len(tier1_matches)} federal/VA/CA/NY citation-shaped string(s) are marked or otherwise accounted for")
print("⚠️ no federal/VA/CA/NY citation-shaped strings found — confirm this document didn't need any")
# Generic tier: strings that look like "Reporter. 123" but aren't one of
# the Tier 1 patterns. Report separately and always as UNVERIFIED —
# this tier only tells you the shape is citation-like, nothing more.
def overlaps_tier1(start: int, end: int) -> bool:
return any(not (end <= s or start >= e) for s, e in tier1_spans)
m for m in CITATION_SHAPE_GENERIC.finditer(text)
if not overlaps_tier1(m.start(), m.end())
1 for m in generic_matches if not _is_marked(text, m.start(), m.end())
if generic_matches and unflagged_generic:
print(f"❌ {unflagged_generic} generic-tier (UNVERIFIED reporter shape, not federal/VA/CA/NY) citation-shaped string(s) with no nearby marker")
print(f"⚠️ {len(generic_matches)} generic-tier (UNVERIFIED reporter shape) citation-shaped string(s) are marked — still confirm the reporter/citation is real before relying on it")
if any(marker in text.lower() for marker in DISCLAIMER_MARKERS):
print("✅ attorney-review disclaimer language present")
print("❌ no attorney-review disclaimer found — every draft needs the verbatim disclaimer block")
print("Usage: check_legal_doc.py <document.md> [<document2.md> ...]", file=sys.stderr)
for path in sys.argv[1:]:
worst = max(worst, check_file(path))
if __name__ == "__main__":