From fdcd5c8fb1d0a71aec1455cd648f039e0457a4c0 Mon Sep 17 00:00:00 2001 From: Anil Baris Devran Date: Sat, 25 Jul 2026 10:12:36 +0300 Subject: [PATCH 1/5] fix(scanners): scan markdown prose, report every hit, exact closer lines - copy_scan.py: stop exempting headings, blockquotes, * bullets, and table cells from the em-dash rule (the suppression regex was inherited from a web-source scanner). Code stays out of scope via stateful fence tracking, blank-line-anchored indented blocks, and inline-code blanking. - copy_scan.py: report all non-overlapping matches per line instead of breaking after the first, and flag en dashes alongside em dashes. - structural_scan.py: group paragraphs with real line numbers so tidy_closer hits are not offset by trailing blank lines. - add tests/run_tests.sh (16 fixture assertions) and .gitattributes. --- .gitattributes | 3 + .../humanizer/scripts}/copy_scan.py | 60 ++++++-- .../scripts/structural_scan.py | 33 +++-- tests/run_tests.sh | 138 ++++++++++++++++++ 4 files changed, 210 insertions(+), 24 deletions(-) create mode 100644 .gitattributes rename {scripts => skills/humanizer/scripts}/copy_scan.py (73%) mode change 100755 => 100644 create mode 100644 tests/run_tests.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3a802d2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +* text=auto +*.sh text eol=lf +*.py text eol=lf diff --git a/scripts/copy_scan.py b/skills/humanizer/scripts/copy_scan.py old mode 100755 new mode 100644 similarity index 73% rename from scripts/copy_scan.py rename to skills/humanizer/scripts/copy_scan.py index d6a3c25..951d422 --- a/scripts/copy_scan.py +++ b/skills/humanizer/scripts/copy_scan.py @@ -1,13 +1,14 @@ #!/usr/bin/env python3 """copy_scan.py - deterministic scan for surface copy tells in prose. -Ported from devibe_scan.py in jcarterjohnson/vibecoded-design-tells (MIT), -narrowed to the four mechanical copy rules and adapted for prose files -(markdown, plain text, HTML) rather than web source. +Ported from devibe_scan.py in jcarterjohnson/vibecoded-design-tells, +Copyright (c) 2026 Carter Johnson, MIT License. Narrowed to the four +mechanical copy rules and adapted for prose files (markdown, plain text, +HTML) rather than web source. Catches the pattern-matchable slice of the surface layer: - copy-em-dash em dash in visible copy (the #1 cited writing tell, 7.1%) + copy-em-dash em dash in visible copy (most-cited writing tell, 7.1%) copy-antithesis "it's not just X, it's Y" / "not only X but Y" (2.8%) hype-copy marketing cliche vocabulary copy-servile sycophantic openers and signposted wrap-ups @@ -22,6 +23,10 @@ python3 copy_scan.py --json draft.md # machine-readable output python3 copy_scan.py --strict draft.md # exit 1 on any hit (hook-friendly) +Prose in headings, blockquotes, bullets, and tables IS user-facing copy and is +scanned. Fenced code blocks, indented code blocks, inline code spans, and +comment lines are not copy and are skipped. + Mark a line with `copy-ignore` to suppress it (intentional usage). """ @@ -34,11 +39,13 @@ RULES = [ { "id": "copy-em-dash", - "label": "Em dash in copy (the #1 'AI wrote this' writing tell)", + "label": "Em/en dash in copy (the most-cited 'AI wrote this' writing tell)", "fix": "Use a comma, a period, or parentheses. Not a colon; that gets flagged too.", - "pats": [r"\w\s*—\s*\w", r"\w\s*—\s*\w"], - # Skip code, code comments, and fenced blocks: not user-facing copy. - "suppress": r"^\s*(\*|//|/\*|