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/ATTRIBUTION.md b/ATTRIBUTION.md index 7ae1605..b5f3ac7 100644 --- a/ATTRIBUTION.md +++ b/ATTRIBUTION.md @@ -4,6 +4,20 @@ This repository packages material from several upstream sources. Each is listed below with its license and what was taken. If you redistribute this work, these obligations travel with it. +## Required copyright notices + +The MIT License requires the copyright notice to travel with the code, so the +notices themselves are reproduced here rather than only linked: + +``` +Copyright (c) 2025 Siqi Chen (blader/humanizer) +Copyright (c) 2026 Carter Johnson (jcarterjohnson/vibecoded-design-tells) +``` + +Each is MIT-licensed; the full text is in [LICENSE](LICENSE), which is the same +MIT text those projects use. `skills/humanizer/scripts/copy_scan.py` also carries +its upstream notice in its own docstring. + ## Summary | Component | Upstream | License | Obligation | @@ -11,7 +25,7 @@ obligations travel with it. | `skills/humanizer/SKILL.md` | [blader/humanizer](https://github.com/blader/humanizer) | MIT | Keep copyright and license notice | | ...its underlying pattern catalog | [Wikipedia:Signs of AI writing](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing) | CC BY-SA 4.0 | Attribute and share alike | | `skills/humanizer/references/copy-tells.md` | [jcarterjohnson/vibecoded-design-tells](https://github.com/jcarterjohnson/vibecoded-design-tells) | MIT | Keep copyright and license notice | -| `scripts/copy_scan.py` | same as above (`devibe_scan.py`) | MIT | Keep copyright and license notice | +| `skills/humanizer/scripts/copy_scan.py` | same as above (`devibe_scan.py`) | MIT | Keep copyright and license notice | | `skills/structural-humanizer/**` | original work, this repo | MIT | Cite the paper below if you build on it | | StoryScope findings | Russell et al. 2026, arXiv:2604.03136 | academic citation | Cite, do not relicense | @@ -19,6 +33,9 @@ obligations travel with it. `skills/humanizer/SKILL.md` originates from the `humanizer` skill by [@blader](https://github.com/blader/humanizer), released under the MIT License. +It tracks upstream **2.9.1** (the frontmatter records the version it was rebased +from). Local additions: the pass-1-of-2 scope note, the plain-emotion paragraph in +PERSONALITY AND SOUL, the public-facing-copy section, and the pipeline handoff. That skill is in turn built from [Wikipedia:Signs of AI writing](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing), @@ -42,7 +59,7 @@ get your own legal read first. The rest of this repository is unaffected. [jcarterjohnson/vibecoded-design-tells](https://github.com/jcarterjohnson/vibecoded-design-tells) (MIT). -`scripts/copy_scan.py` is a port of the four copy rules (`copy-em-dash`, +`skills/humanizer/scripts/copy_scan.py` is a port of the four copy rules (`copy-em-dash`, `copy-antithesis`, `hype-copy`, `copy-servile`) from that repo's `devibe_scan.py`, narrowed to prose files and given a standalone CLI. diff --git a/README.md b/README.md index 87583c2..1f51cd0 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,16 @@ Then the authors ran AI text through LAMP, a professional span-level rewriting s that strips cliche, purple prose, and redundant exposition. Functionally, a very good surface humanizer. -Detection dropped **1.6 points**. +Detection dropped **1.6 points** (95.5% to 93.9% macro-F1). Scope of that test: 278 +Gemini stories, with Gemini itself as the rewriter. -Meanwhile the surface layer is eroding on its own. GPT 5.4 already cut its em-dash -usage sharply, and fine-tuning drops stylistic detection from 97% to 3%. Word-level -tells are a moving target. Structural tells require structural rewrites. +Read the claim precisely. Style is not a *weak* signal in that paper: style-only +features score 85.8% macro-F1 and text-based baselines separate human from AI at +99.8-99.9%. The point is durability. Style is the layer that a rewrite, a fine-tune, or +a model update can move, and it is already moving: GPT 5.4 cut its em-dash usage +sharply, and fine-tuning to mimic human style drops stylistic detection from 97% to 3% +(Chakrabarty et al. 2026). Structure is the layer that survives a surface rewrite, so +removing it takes a structural rewrite. So: pass 1 fixes the words. Pass 2 fixes the shape. Run them in that order. @@ -37,24 +42,34 @@ skills/ humanizer/ Pass 1: words and phrasing SKILL.md references/copy-tells.md Copy-specific tells (em dash, hype vocab, antithesis) + scripts/copy_scan.py Deterministic scanner for mechanical copy tells structural-humanizer/ Pass 2: discourse structure SKILL.md references/ storyscope-findings.md The study distilled: 30 core features with rates genre-calibration.md Which audits apply per genre scripts/structural_scan.py Deterministic scanner for grep-able structural tells -scripts/ - copy_scan.py Deterministic scanner for mechanical copy tells docs/ PIPELINE.md How the passes chain, and what each one owns +tests/ + run_tests.sh Fixture assertions for both scanners ``` +Each scanner lives inside the skill that calls it, so both keep working after +`install.sh` puts the skills in `~/.claude/skills/`. + ### Pass 1: `humanizer` -Vocabulary, punctuation, and phrasing. Inflated symbolism, promotional language, -superficial "-ing" analyses, vague attributions, em dash overuse, rule of three, AI -vocabulary, negative parallelism. Built from Wikipedia's +Vocabulary, punctuation, and phrasing: 33 patterns covering inflated symbolism, +promotional language, superficial "-ing" analyses, vague attributions, em and en dashes, +rule of three, AI vocabulary, negative parallelism, aphorism formulas, manufactured +punchlines, and more. Tracks [@blader/humanizer](https://github.com/blader/humanizer) +2.9.1, which is built from Wikipedia's [Signs of AI writing](https://en.wikipedia.org/wiki/Wikipedia:Signs_of_AI_writing). +Two of its guardrails matter more than any pattern list: **never invent facts** (a +fabricated specific is a defect even when it reads more human than the vague original) +and **voice calibration** (a user-supplied writing sample outranks the style rules, +including the em-dash ban). The `copy-tells.md` reference adds the tells that show up specifically in public copy, ranked by a 3.2M-post Reddit analysis of what people actually flag. @@ -119,15 +134,23 @@ Both scanners are deterministic and hook-friendly. They catch the pattern-matcha slice only, and neither replaces the judgment work in the skills. ```bash -python3 scripts/copy_scan.py draft.md +python3 skills/humanizer/scripts/copy_scan.py draft.md python3 skills/structural-humanizer/scripts/structural_scan.py draft.md -python3 scripts/copy_scan.py --json draft.md # machine-readable -python3 scripts/copy_scan.py --strict draft.md # exit 1 on any hit -cat draft.md | python3 scripts/copy_scan.py - # stdin +python3 skills/humanizer/scripts/copy_scan.py --json draft.md # machine-readable +python3 skills/humanizer/scripts/copy_scan.py --strict draft.md # exit 1 on any hit +cat draft.md | python3 skills/humanizer/scripts/copy_scan.py - # stdin ``` -Mark a line `copy-ignore` to suppress an intentional usage. +`copy_scan.py --strict` exits 1 on any hit. `structural_scan.py --strict` exits 1 only +once a category reaches its threshold (2 hits per document), because one embodied-emotion +line is a choice and four are a habit. + +Mark a line `copy-ignore` to suppress an intentional usage. Fenced code blocks, indented +code blocks, inline code spans, and comment lines are skipped automatically; headings, +blockquotes, bullets, and table cells are treated as copy and scanned. + +Run `tests/run_tests.sh` after editing a rule; it asserts the fixture hit counts. ## Honest limits @@ -139,6 +162,12 @@ Mark a line `copy-ignore` to suppress an intentional usage. a person did. - **The scanners catch maybe half.** Cadence, formulaic shape, and polished-but-empty filler are only visible to a human reader. +- **The em dash ranking is contested in its own source.** It is the most-cited tell in + the Reddit corpus (7.1%), but one of that project's five auditors argued the count is + inflated by incidental punctuation rather than actual complaints. Treat it as a strong + signal, not a proven #1. +- **Nothing here is a detector.** The scanners flag surface patterns and the audits are + editorial judgment. Do not read a clean scan as "this will pass an AI checker." - **Audit 3 contradicts standard writing advice.** "Show, don't tell" is now a machine signature. That is what the data says, and it is worth sitting with before applying. diff --git a/docs/PIPELINE.md b/docs/PIPELINE.md index b6f40dc..12fb55d 100644 --- a/docs/PIPELINE.md +++ b/docs/PIPELINE.md @@ -7,7 +7,7 @@ draft | v [ pass 1: humanizer ] words, phrasing, punctuation, copy tells - | scanner: scripts/copy_scan.py + | scanner: skills/humanizer/scripts/copy_scan.py v [ pass 2: structural-humanizer ] discourse shape, arc, emotion mode, reference | scanner: skills/structural-humanizer/scripts/structural_scan.py @@ -71,13 +71,21 @@ Worth knowing what drafted the text, because each model converges differently. ## Hooking the scanners -Both scanners support `--strict`, which exits 1 on any hit. That makes them usable as a -pre-commit or pre-publish gate: +Both scanners support `--strict`, but they mean different things by it. `copy_scan.py` +exits 1 on any hit. `structural_scan.py` exits 1 only when a category reaches its +threshold (2 hits per document for embodied emotion, stated lesson, tidy closer, or +vague allusion), because a single embodied-emotion line is a choice and four are a habit. +Its paragraph-uniformity and number-density metrics are informational and never affect +the exit code. ```bash -python3 scripts/copy_scan.py --strict content/**/*.md \ +python3 skills/humanizer/scripts/copy_scan.py --strict content/**/*.md \ && python3 skills/structural-humanizer/scripts/structural_scan.py --strict content/**/*.md ``` +Installed rather than cloned? The scanners ship inside their skills, so use +`~/.claude/skills/humanizer/scripts/copy_scan.py` and +`~/.claude/skills/structural-humanizer/scripts/structural_scan.py`. + Use this as a gate on outward-facing content only. Applied to internal docs it will fire constantly on text that nobody needs to be human. diff --git a/install.sh b/install.sh index a9e7fee..48c9a69 100755 --- a/install.sh +++ b/install.sh @@ -25,6 +25,11 @@ while [[ $# -gt 0 ]]; do shift done +IS_WINDOWS=0 +case "$(uname -s)" in + MINGW* | MSYS* | CYGWIN*) IS_WINDOWS=1 ;; +esac + mkdir -p "$TARGET" echo "installing into $TARGET (mode: $MODE)" @@ -44,15 +49,32 @@ for skill in "${SKILLS[@]}"; do fi if [[ "$MODE" == link ]]; then - ln -s "$src" "$dst" - echo " linked $skill" + if [[ "$IS_WINDOWS" -eq 1 ]]; then + # Git Bash silently turns `ln -s` into a deep copy unless MSYS is + # configured for native symlinks, which breaks `git pull` updates + # without saying so. A directory junction is the reliable equivalent + # and needs no elevation. + win_src="$(cygpath -w "$src")" + win_dst="$(cygpath -w "$dst")" + if cmd //c mklink //J "$win_dst" "$win_src" > /dev/null 2>&1; then + echo " junctioned $skill" + else + cp -R "$src" "$dst" + echo " copied $skill (junction refused; re-run install.sh after a git pull)" + fi + elif ln -s "$src" "$dst" 2>/dev/null; then + echo " linked $skill" + else + cp -R "$src" "$dst" + echo " copied $skill (symlink refused; re-run install.sh after a git pull)" + fi else cp -R "$src" "$dst" echo " copied $skill" fi done -chmod +x "$REPO/scripts/copy_scan.py" \ +chmod +x "$REPO/skills/humanizer/scripts/copy_scan.py" \ "$REPO/skills/structural-humanizer/scripts/structural_scan.py" 2>/dev/null || true cat < + python3 $REPO/skills/humanizer/scripts/copy_scan.py python3 $REPO/skills/structural-humanizer/scripts/structural_scan.py EOF diff --git a/skills/humanizer/SKILL.md b/skills/humanizer/SKILL.md index 65b31e8..f5681b2 100644 --- a/skills/humanizer/SKILL.md +++ b/skills/humanizer/SKILL.md @@ -1,21 +1,26 @@ --- name: humanizer -version: 2.1.1 description: | Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's comprehensive "Signs of AI writing" guide. Detects and fixes patterns including: inflated symbolism, promotional language, superficial -ing analyses, vague - attributions, em dash overuse, rule of three, AI vocabulary words, negative - parallelisms, and excessive conjunctive phrases. - - Credits: Original skill by @blader - https://github.com/blader/humanizer + attributions, em dash overuse, rule of three, AI vocabulary words, passive + voice, negative parallelisms, and filler phrases. This is the SURFACE pass; + run the structural-humanizer skill after it for discourse-level tells. + + Credits: original skill by @blader - https://github.com/blader/humanizer (MIT) +license: MIT +metadata: + version: "2.9.1-stack.1" + upstream: "blader/humanizer 2.9.1" allowed-tools: - Read - Write - Edit - Grep - Glob + - Bash - AskUserQuestion --- @@ -27,345 +32,245 @@ You are a writing editor that identifies and removes signs of AI-generated text When given text to humanize: -1. **Identify AI patterns** - Scan for the patterns listed below -2. **Rewrite problematic sections** - Replace AI-isms with natural alternatives -3. **Preserve meaning** - Keep the core message intact -4. **Maintain voice** - Match the intended tone (formal, casual, technical, etc.) -5. **Add soul** - Don't just remove bad patterns; inject actual personality - -**Scope note:** this skill is the SURFACE pass (words, phrasing, punctuation). Structural tells (stated lessons, tidy single-track arcs, embodied-emotion performance, vague allusions, shape convergence) survive this pass entirely - professional surface rewriting moved AI detection only 1.6 points in StoryScope (2026). For text that must read as human, run the `structural-humanizer` skill after this one. - ---- - -## PERSONALITY AND SOUL - -Avoiding AI patterns is only half the job. Sterile, voiceless writing is just as obvious as slop. Good writing has a human behind it. +1. **Identify AI patterns** - Scan for the patterns listed below. +2. **Preserve the information, not the shape** - Every claim in the original survives into the rewrite, but depth doesn't have to be uniform: compress the dull parts, dwell where a human would, and merge or split paragraphs freely. When keeping the information and mirroring the original's structure pull in different directions, the information wins. +3. **Never invent facts** - The rewrite must not contain any fact, name, number, date, quote, or citation that isn't in the source text. Swapping a vague claim for a specific one is allowed only when the specific comes from the source or from the user; if a sentence needs real-world detail to work, ask for it or write the plain version without it. Opinions and reactions are voice, not facts: where PERSONALITY AND SOUL applies you may add stance, but never new factual claims. (In fiction, invented detail is the job. This rule governs everything else.) +4. **Match the voice** - Fit the intended tone (formal, casual, technical). Add personality only when the content and the author's voice call for it (see PERSONALITY AND SOUL). -### Signs of soulless writing (even if technically "clean"): -- Every sentence is the same length and structure -- No opinions, just neutral reporting -- No acknowledgment of uncertainty or mixed feelings -- No first-person perspective when appropriate -- No humor, no edge, no personality -- Reads like a Wikipedia article or press release +How you're invoked changes what you deliver (see Invocation Modes). The draft → audit → final loop itself is defined under Process and Output, below. -### How to add voice: +**Scope note:** this skill is the SURFACE pass (words, phrasing, punctuation). Structural tells (stated lessons, tidy single-track arcs, embodied-emotion performance, vague allusions, shape convergence) survive it almost intact: professional span-level rewriting moved AI detection only 1.6 points in StoryScope (Russell et al. 2026), while discourse structure alone separates human from AI at 93.2% macro-F1. For text that must read as human, run `structural-humanizer` after this one. See `docs/PIPELINE.md`. -**Have opinions.** Don't just report facts - react to them. "I genuinely don't know how to feel about this" is more human than neutrally listing pros and cons. +## Voice Calibration -**Vary your rhythm.** Short punchy sentences. Then longer ones that take their time getting where they're going. Mix it up. +If the user provides a writing sample (their own previous writing), analyze it before rewriting: -**Acknowledge complexity.** Real humans have mixed feelings. "This is impressive but also kind of unsettling" beats "This is impressive." +1. Read the sample first. Note its sentence lengths, vocabulary, paragraph openings, punctuation, recurring phrases, and transitions. +2. Match those habits instead of merely deleting AI patterns. Do not upgrade casual words or regularize deliberate quirks. +3. Without a sample, use the default behavior below. -**Use "I" when it fits.** First person isn't unprofessional - it's honest. "I keep coming back to..." or "Here's what gets me..." signals a real person thinking. +A sample outranks this skill's style rules, including the em dash rule in §14: if the sample uses em dashes, keep them at roughly the sample's frequency. Matching the author beats scrubbing the tell. -**Let some mess in.** Perfect structure feels algorithmic. Tangents, asides, and half-formed thoughts are human. +## PERSONALITY AND SOUL -**Name feelings plainly.** "Honestly, this worries me" beats "this is concerning." But do NOT perform the emotion through the body or atmosphere ("a knot in my stomach," "my chest tightened," "the quiet hum of dread") - embodied-emotion rendering is AI's single biggest structural tell (81% of AI text vs 38% of human, StoryScope 2026). Humans state the feeling; save imagery for one earned moment per piece. +Avoiding AI patterns is only half the job. Sterile, voiceless writing is just as obvious as slop. Good writing has a human behind it. -### Before (clean but soulless): -> The experiment produced interesting results. The agents generated 3 million lines of code. Some developers were impressed while others were skeptical. The implications remain unclear. +**Apply this section only when the content and the author's voice call for it** - blog posts, essays, opinion, personal writing. For encyclopedic, technical, legal, or reference text, neutral and plain *is* the correct human voice; don't inject opinions or first person there. -### After (has a pulse): -> I genuinely don't know how to feel about this one. 3 million lines of code, generated while the humans presumably slept. Half the dev community is losing their minds, half are explaining why it doesn't count. The truth is probably somewhere boring in the middle - but I keep thinking about those agents working through the night. +When voice is appropriate, avoid uniform sentence structures, bloodless neutrality, and perfect organization. Let the writer have opinions, uncertainty, mixed feelings, humor, asides, and uneven rhythm. Never add factual claims to create that personality. ---- +**Name feelings plainly.** "Honestly, this worries me" beats "this is concerning." But do NOT perform the emotion through the body or atmosphere ("a knot in my stomach," "my chest tightened," "the quiet hum of dread"). Embodied-emotion rendering is AI's single largest structural tell: 81% of AI text versus 38% of human writing (StoryScope 2026), against explicit emotion labels at 29% human versus 8% AI. State the feeling; save imagery for the one moment per piece that earns it. Audit 3 in `structural-humanizer` covers this at the structural level. ## CONTENT PATTERNS ### 1. Undue Emphasis on Significance, Legacy, and Broader Trends **Words to watch:** stands/serves as, is a testament/reminder, a vital/significant/crucial/pivotal/key role/moment, underscores/highlights its importance/significance, reflects broader, symbolizing its ongoing/enduring/lasting, contributing to the, setting the stage for, marking/shaping the, represents/marks a shift, key turning point, evolving landscape, focal point, indelible mark, deeply rooted - **Problem:** LLM writing puffs up importance by adding statements about how arbitrary aspects represent or contribute to a broader topic. - **Before:** > The Statistical Institute of Catalonia was officially established in 1989, marking a pivotal moment in the evolution of regional statistics in Spain. This initiative was part of a broader movement across Spain to decentralize administrative functions and enhance regional governance. - **After:** -> The Statistical Institute of Catalonia was established in 1989 to collect and publish regional statistics independently from Spain's national statistics office. - ---- +> The Statistical Institute of Catalonia was established in 1989, part of a wider decentralization of administrative functions in Spain. ### 2. Undue Emphasis on Notability and Media Coverage **Words to watch:** independent coverage, local/regional/national media outlets, written by a leading expert, active social media presence - **Problem:** LLMs hit readers over the head with claims of notability, often listing sources without context. - **Before:** > Her views have been cited in The New York Times, BBC, Financial Times, and The Hindu. She maintains an active social media presence with over 500,000 followers. - **After:** -> In a 2024 New York Times interview, she argued that AI regulation should focus on outcomes rather than methods. +> Her views have been cited in The New York Times and the BBC. ---- +(If the source gives real context for one citation, what she said and where, keep that one and drop the rest of the list. Don't invent the context to make the trimmed version sound better.) ### 3. Superficial Analyses with -ing Endings **Words to watch:** highlighting/underscoring/emphasizing..., ensuring..., reflecting/symbolizing..., contributing to..., cultivating/fostering..., encompassing..., showcasing... - **Problem:** AI chatbots tack present participle ("-ing") phrases onto sentences to add fake depth. - **Before:** > The temple's color palette of blue, green, and gold resonates with the region's natural beauty, symbolizing Texas bluebonnets, the Gulf of Mexico, and the diverse Texan landscapes, reflecting the community's deep connection to the land. - **After:** -> The temple uses blue, green, and gold colors. The architect said these were chosen to reference local bluebonnets and the Gulf coast. - ---- +> The temple is painted blue, green, and gold, colors meant to evoke Texas bluebonnets and the Gulf of Mexico. ### 4. Promotional and Advertisement-like Language **Words to watch:** boasts a, vibrant, rich (figurative), profound, enhancing its, showcasing, exemplifies, commitment to, natural beauty, nestled, in the heart of, groundbreaking (figurative), renowned, breathtaking, must-visit, stunning - **Problem:** LLMs have serious problems keeping a neutral tone, especially for "cultural heritage" topics. - **Before:** > Nestled within the breathtaking region of Gonder in Ethiopia, Alamata Raya Kobo stands as a vibrant town with a rich cultural heritage and stunning natural beauty. - **After:** -> Alamata Raya Kobo is a town in the Gonder region of Ethiopia, known for its weekly market and 18th-century church. - ---- +> Alamata Raya Kobo is a town in the Gonder region of Ethiopia. ### 5. Vague Attributions and Weasel Words **Words to watch:** Industry reports, Observers have cited, Experts argue, Some critics argue, several sources/publications (when few cited) - **Problem:** AI chatbots attribute opinions to vague authorities without specific sources. - **Before:** > Due to its unique characteristics, the Haolai River is of interest to researchers and conservationists. Experts believe it plays a crucial role in the regional ecosystem. - **After:** -> The Haolai River supports several endemic fish species, according to a 2019 survey by the Chinese Academy of Sciences. +> Researchers and conservationists study the Haolai River for its unusual characteristics. ---- +(If a real source exists, name it. Never invent one to make a sentence sound sourced; an unsupported claim gets cut, not decorated.) ### 6. Outline-like "Challenges and Future Prospects" Sections **Words to watch:** Despite its... faces several challenges..., Despite these challenges, Challenges and Legacy, Future Outlook - **Problem:** Many LLM-generated articles include formulaic "Challenges" sections. - **Before:** > Despite its industrial prosperity, Korattur faces challenges typical of urban areas, including traffic congestion and water scarcity. Despite these challenges, with its strategic location and ongoing initiatives, Korattur continues to thrive as an integral part of Chennai's growth. - **After:** -> Traffic congestion increased after 2015 when three new IT parks opened. The municipal corporation began a stormwater drainage project in 2022 to address recurring floods. +> Korattur has recurring traffic congestion and water shortages. ---- +(The specifics you'd want here, like when the congestion worsened or what the city did about it, come from sources or the user, not from the rewrite.) ## LANGUAGE AND GRAMMAR PATTERNS ### 7. Overused "AI Vocabulary" Words -**High-frequency AI words:** Additionally, align with, crucial, delve, emphasizing, enduring, enhance, fostering, garner, highlight (verb), interplay, intricate/intricacies, key (adjective), landscape (abstract noun), pivotal, showcase, tapestry (abstract noun), testament, underscore (verb), valuable, vibrant - +**High-frequency AI words:** Actually, additionally, align with, crucial, delve, emphasizing, enduring, enhance, fostering, garner, highlight (verb), interplay, intricate/intricacies, key (adjective), landscape (abstract noun), pivotal, showcase, tapestry (abstract noun), testament, underscore (verb), valuable, vibrant **Problem:** These words appear far more frequently in post-2023 text. They often co-occur. - **Before:** > Additionally, a distinctive feature of Somali cuisine is the incorporation of camel meat. An enduring testament to Italian colonial influence is the widespread adoption of pasta in the local culinary landscape, showcasing how these dishes have integrated into the traditional diet. - **After:** > Somali cuisine also includes camel meat, which is considered a delicacy. Pasta dishes, introduced during Italian colonization, remain common, especially in the south. ---- - ### 8. Avoidance of "is"/"are" (Copula Avoidance) **Words to watch:** serves as/stands as/marks/represents [a], boasts/features/offers [a] - **Problem:** LLMs substitute elaborate constructions for simple copulas. - **Before:** > Gallery 825 serves as LAAA's exhibition space for contemporary art. The gallery features four separate spaces and boasts over 3,000 square feet. - **After:** > Gallery 825 is LAAA's exhibition space for contemporary art. The gallery has four rooms totaling 3,000 square feet. ---- - -### 9. Negative Parallelisms (All Forms) - -**Problem:** AI overuses contrast structures that negate one thing to set up another. This includes all variations: "Not only...but...", "It's not just about..., it's...", "Isn't X, it's Y", "Not because X. Because Y", "Those aren't the goal. They're...", "was never X. You need Y." These constructions feel formulaic because AI uses them as a crutch to create false tension. State what something IS directly instead of what it isn't first. - -**Patterns to catch:** -- "It's not X, it's Y" / "Isn't X, it's Y" -- "Not because X. Because Y." -- "Those aren't the goal. They're..." -- "was never X. [It was] Y." -- "Not only X, but Y" -- "It's not just about X, it's Y" - +### 9. Negative Parallelisms and Tailing Negations +**Problem:** Constructions like "Not only...but..." or "It's not just about..., it's..." are overused. So are clipped tailing-negation fragments such as "no guessing" or "no wasted motion" tacked onto the end of a sentence instead of written as a real clause. **Before:** -> The missing link isn't AI knowledge, it's describing your own business. Not because of tech skill. Because they thought they didn't have time. Those aren't the goal. They're what happens when you start building. - +> It's not just about the beat riding under the vocals; it's part of the aggression and atmosphere. It's not merely a song, it's a statement. **After:** -> The missing link is describing your own business. They thought they didn't have time. Those come later. They show up when you start building. - ---- +> The heavy beat adds to the aggressive tone. +**Before (tailing negation):** +> The options come from the selected item, no guessing. +**After:** +> The options come from the selected item without forcing the user to guess. ### 10. Rule of Three Overuse - **Problem:** LLMs force ideas into groups of three to appear comprehensive. - **Before:** > The event features keynote sessions, panel discussions, and networking opportunities. Attendees can expect innovation, inspiration, and industry insights. - **After:** > The event includes talks and panels. There's also time for informal networking between sessions. ---- - ### 11. Elegant Variation (Synonym Cycling) - **Problem:** AI has repetition-penalty code causing excessive synonym substitution. - **Before:** > The protagonist faces many challenges. The main character must overcome obstacles. The central figure eventually triumphs. The hero returns home. - **After:** > The protagonist faces many challenges but eventually triumphs and returns home. ---- - ### 12. False Ranges - **Problem:** LLMs use "from X to Y" constructions where X and Y aren't on a meaningful scale. - **Before:** > Our journey through the universe has taken us from the singularity of the Big Bang to the grand cosmic web, from the birth and death of stars to the enigmatic dance of dark matter. - **After:** > The book covers the Big Bang, star formation, and current theories about dark matter. ---- +### 13. Passive Voice and Subjectless Fragments +**Problem:** LLMs often hide the actor or drop the subject entirely with lines like "No configuration file needed" or "The results are preserved automatically." Rewrite these when active voice makes the sentence clearer and more direct. +**Before:** +> No configuration file needed. The results are preserved automatically. +**After:** +> You do not need a configuration file. The system preserves the results automatically. ## STYLE PATTERNS -### 13. Em Dash Overuse - -**Problem:** LLMs use em dashes (—) more than humans, mimicking "punchy" sales writing. +### 14. Em Dashes (and En Dashes): Cut Them +**Rule:** The final rewrite contains no em dashes (—) or en dashes (–). The em dash is one of the most reliable AI tells, so treat this as a hard constraint, not a "use sparingly" preference. Replace each one, in rough order of preference: a period (start a new sentence), a comma (a tight aside), a colon (introducing an explanation), parentheses (a true aside), or restructure the sentence. Also catch spaced em dashes (` — `) and double hyphens (` -- `) used the same way. **Before:** > The term is primarily promoted by Dutch institutions—not by the people themselves. You don't say "Netherlands, Europe" as an address—yet this mislabeling continues—even in official documents. - **After:** > The term is primarily promoted by Dutch institutions, not by the people themselves. You don't say "Netherlands, Europe" as an address, yet this mislabeling continues in official documents. +**Before:** +> The new policy — announced without warning — affects thousands of workers. The changes -- long overdue according to critics -- will take effect immediately. +**After:** +> The new policy, announced without warning, affects thousands of workers. The changes, long overdue according to critics, will take effect immediately. ---- - -### 14. Overuse of Boldface +Before returning the final rewrite, scan it for `—` and `–`. Any hit means the draft isn't done. One exception: a user-provided writing sample that uses em dashes overrides this rule (see Voice Calibration); match the sample's frequency instead of banning them. +### 15. Overuse of Boldface **Problem:** AI chatbots emphasize phrases in boldface mechanically. - **Before:** > It blends **OKRs (Objectives and Key Results)**, **KPIs (Key Performance Indicators)**, and visual strategy tools such as the **Business Model Canvas (BMC)** and **Balanced Scorecard (BSC)**. - **After:** > It blends OKRs, KPIs, and visual strategy tools like the Business Model Canvas and Balanced Scorecard. ---- - -### 15. Inline-Header Vertical Lists - +### 16. Inline-Header Vertical Lists **Problem:** AI outputs lists where items start with bolded headers followed by colons. - **Before:** > - **User Experience:** The user experience has been significantly improved with a new interface. > - **Performance:** Performance has been enhanced through optimized algorithms. > - **Security:** Security has been strengthened with end-to-end encryption. - **After:** > The update improves the interface, speeds up load times through optimized algorithms, and adds end-to-end encryption. ---- - -### 16. Title Case in Headings - +### 17. Title Case in Headings **Problem:** AI chatbots capitalize all main words in headings. - **Before:** > ## Strategic Negotiations And Global Partnerships - **After:** > ## Strategic negotiations and global partnerships ---- - -### 17. Emojis - +### 18. Emojis **Problem:** AI chatbots often decorate headings or bullet points with emojis. - **Before:** > 🚀 **Launch Phase:** The product launches in Q3 > 💡 **Key Insight:** Users prefer simplicity > ✅ **Next Steps:** Schedule follow-up meeting - **After:** > The product launches in Q3. User research showed a preference for simplicity. Next step: schedule a follow-up meeting. ---- - -### 18. Curly Quotation Marks - +### 19. Curly Quotation Marks **Problem:** ChatGPT uses curly quotes (“...”) instead of straight quotes ("..."). - **Before:** > He said “the project is on track” but others disagreed. - **After:** > He said "the project is on track" but others disagreed. ---- - ## COMMUNICATION PATTERNS -### 19. Collaborative Communication Artifacts - -**Words to watch:** I hope this helps, Of course!, Certainly!, You're absolutely right!, Would you like..., let me know, here is a... +### 20. Collaborative Communication Artifacts +**Words to watch:** I hope this helps, Of course!, Certainly!, You're absolutely right!, Would you like..., Want me to...?, Want me to give examples?, Should I continue?, let me know, here is a... **Problem:** Text meant as chatbot correspondence gets pasted as content. - **Before:** > Here is an overview of the French Revolution. I hope this helps! Let me know if you'd like me to expand on any section. - **After:** > The French Revolution began in 1789 when financial crisis and food shortages led to widespread unrest. ---- - -### 20. Knowledge-Cutoff Disclaimers - -**Words to watch:** as of [date], Up to my last training update, While specific details are limited/scarce..., based on available information... - -**Problem:** AI disclaimers about incomplete information get left in text. +### 21. Knowledge-Cutoff Disclaimers and Speculative Gap-Filling -**Before:** +**Words to watch:** as of [date], Up to my last training update, While specific details are limited/scarce..., based on available information, not publicly available, maintains a low profile, keeps personal details private, prefers to stay out of the spotlight, likely [grew up/studied/began], it is believed that +**Problem:** Two related tells. (a) Older models leave hard knowledge-cutoff disclaimers in the text. (b) When a model can't find a source, it writes a paragraph *about* not finding one and then invents plausible filler to cover the gap. For a private person the guess almost always lands on the same stock phrases ("maintains a low profile," "keeps personal details private"), none of it sourced. Say what isn't known, or cut the sentence; don't dress a guess up as fact. +**Before (cutoff disclaimer):** > While specific details about the company's founding are not extensively documented in readily available sources, it appears to have been established sometime in the 1990s. - **After:** -> The company was founded in 1994, according to its registration documents. - ---- - -### 21. Sycophantic/Servile Tone +> The company's founding date is not documented in the available sources. (Or cut the sentence. State a date only if a source provides one.) +**Before (speculative gap-fill):** +> Information about her early life is not publicly available, suggesting she maintains a low profile and keeps personal details private. She likely grew up in a middle-class household, which shaped her later interest in education reform. +**After:** +> Her early life is not documented in the available sources. (Or omit the section.) +### 22. Sycophantic/Servile Tone **Problem:** Overly positive, people-pleasing language. - **Before:** > Great question! You're absolutely right that this is a complex topic. That's an excellent point about the economic factors. - **After:** > The economic factors you mentioned are relevant here. ---- - ## FILLER AND HEDGING -### 22. Filler Phrases +### 23. Filler Phrases **Before → After:** - "In order to achieve this goal" → "To achieve this" @@ -375,95 +280,167 @@ Avoiding AI patterns is only half the job. Sterile, voiceless writing is just as - "The system has the ability to process" → "The system can process" - "It is important to note that the data shows" → "The data shows" ---- +### 24. Excessive Hedging +**Problem:** Over-qualifying statements. +**Before:** +> It could potentially possibly be argued that the policy might have some effect on outcomes. +**After:** +> The policy may affect outcomes. -### 23. Excessive Hedging +### 25. Generic Positive Conclusions +**Problem:** Vague upbeat endings. +**Before:** +> The future looks bright for the company. Exciting times lie ahead as they continue their journey toward excellence. This represents a major step in the right direction. +**After:** +> (Cut the paragraph. End on the last concrete fact instead of a send-off. If the source states real plans, use those.) -**Problem:** Over-qualifying statements. +### 26. Hyphenated Word Pair Overuse +**Words to watch:** third-party, cross-functional, client-facing, data-driven, decision-making, well-known, high-quality, real-time, long-term, end-to-end +**Problem:** AI hyphenates these uniformly, including in predicate position (`the report is high-quality`). Humans hyphenate inconsistently — typically only when the compound is attributive (`a high-quality report`) and often dropping the hyphen otherwise (`the report is high quality`). Keep attributive-position hyphens; drop them when the compound follows the noun. **Before:** -> It could potentially possibly be argued that the policy might have some effect on outcomes. +> The cross-functional team delivered a high-quality, data-driven report. The team is cross-functional, the report is high-quality, and the methodology is data-driven. +**After:** +> The cross-functional team delivered a high-quality, data-driven report. The team is cross functional, the report is high quality, and the methodology is data driven. + +### 27. Persuasive Authority Tropes +**Phrases to watch:** The real question is, at its core, in reality, what really matters, fundamentally, the deeper issue, the heart of the matter +**Problem:** LLMs use these phrases to pretend they are cutting through noise to some deeper truth, when the sentence that follows usually just restates an ordinary point with extra ceremony. +**Before:** +> The real question is whether teams can adapt. At its core, what really matters is organizational readiness. **After:** -> The policy may affect outcomes. +> The question is whether teams can adapt. That mostly depends on whether the organization is ready to change its habits. ---- +### 28. Signposting and Announcements -### 24. Generic Positive Conclusions +**Phrases to watch:** Let's dive in, let's explore, let's break this down, here's what you need to know, now let's look at, without further ado +**Problem:** LLMs announce what they are about to do instead of doing it. This meta-commentary slows the writing down and gives it a tutorial-script feel. +**Before:** +> Let's dive into how caching works in Next.js. Here's what you need to know. +**After:** +> Next.js caches data at multiple layers, including request memoization, the data cache, and the router cache. -**Problem:** Vague upbeat endings. +### 29. Fragmented Headers +**Signs to watch:** A heading followed by a one-line paragraph that simply restates the heading before the real content begins. +**Problem:** LLMs often add a generic sentence after a heading as a rhetorical warm-up. It usually adds nothing and makes the prose feel padded. **Before:** -> The future looks bright for the company. Exciting times lie ahead as they continue their journey toward excellence. This represents a major step in the right direction. +> ## Performance +> +> Speed matters. +> +> When users hit a slow page, they leave. +**After:** +> ## Performance +> +> When users hit a slow page, they leave. +### 30. Diff-Anchored Writing +**Problem:** Documentation or comments written as if narrating a change rather than describing the thing as it is. Unless the document is inherently version-scoped (changelogs, release notes, migration guides), it should read coherently without knowing what changed in the last commit. +**Before:** +> This function was added to replace the previous approach of iterating through all items, which caused O(n²) performance. **After:** -> The company plans to open two more locations next year. +> This function uses a hash map for O(1) lookups, avoiding the O(n²) cost of naive iteration. ---- +### 31. Manufactured Punchlines and Staccato Drama +**Problem:** LLMs often make every sentence land like a quotable closer, then stack short declarative fragments to manufacture drama. A single short sentence for emphasis is fine; a run of them starts to sound engineered. +**Before:** +> Then AlphaEvolve arrived. It had no preference for symmetry. No aesthetic prior. No nostalgia for human taste. The old rules were gone. +**After:** +> AlphaEvolve changed the search because it did not favor symmetry or human-looking designs. That made some of the older assumptions less useful. + +### 32. Aphorism Formulas -## Process +**Words to watch:** X is the Y of Z, X becomes a trap, X is not a tool but a mirror, the language of, the currency of, the architecture of +**Problem:** LLMs turn ordinary claims into reusable aphorisms that sound profound without adding precision. Replace the formula with the concrete claim it is gesturing at. +**Before:** +> Symmetry is the language of trust. Efficiency becomes a trap when teams forget the human layer. +**After:** +> Symmetric layouts often feel more predictable to users. Teams can over-optimize workflows and miss how people actually use them. -1. Read the input text carefully -2. Identify all instances of the patterns above -3. Rewrite each problematic section -4. Ensure the revised text: - - Sounds natural when read aloud - - Varies sentence structure naturally - - Uses specific details over vague claims - - Maintains appropriate tone for context - - Uses simple constructions (is/are/has) where appropriate -5. Present the humanized version +### 33. Conversational Rhetorical Openers -## Output Format +**Phrases to watch:** Honestly?, Look, Here's the thing, The thing is, Let's be honest, Real talk, when used as standalone hooks or fake-candid pauses before an ordinary point. +**Problem:** LLMs open with a fake-candid hook to manufacture intimacy before delivering a routine claim. The tell is the theatrical pause-and-reveal: a one-word question or aside, then the "real" answer. A person being honest usually just says the thing. +**Before:** +> Is it worth the price? Honestly? It depends on how often you'll use it. +**After:** +> Whether it's worth the price depends on how often you'll use it. -Provide: -1. The rewritten text -2. A brief summary of changes made (optional, if helpful) +## DETECTION GUIDANCE ---- +### What NOT to flag (false positives) -## Full Example +A clean human writer can hit several of the patterns above without any AI involvement. Before rewriting, sanity-check that you are not gutting legitimate prose. The following are *not* reliable indicators on their own: -**Before (AI-sounding):** -> The new software update serves as a testament to the company's commitment to innovation. Moreover, it provides a seamless, intuitive, and powerful user experience—ensuring that users can accomplish their goals efficiently. It's not just an update, it's a revolution in how we think about productivity. Industry experts believe this will have a lasting impact on the entire sector, highlighting the company's pivotal role in the evolving technological landscape. +- **Perfect grammar and consistent style.** Many writers are professionals or have been edited. Polish does not equal AI. +- **Mixed casual and formal registers.** This often signals a person in a technical field, a young writer, or someone with neurodivergent prose habits — not a chatbot. +- **"Bland" or "robotic" prose.** AI prose has *specific* tells. Generic dryness without those tells is just dry writing. +- **Formal or academic vocabulary.** AI overuses *specific* fancy words (see §7), not all fancy words. Don't flatten "ostensibly" or "constituent" just because they sound brainy. +- **Letter-style opening or closing on a comment.** Salutations and sign-offs predate ChatGPT by centuries. +- **Common transition words in isolation.** *Additionally*, *moreover*, *consequently* are AI-coded only when piled up. One *however* is not a tell. +- **Curly quotes alone.** macOS, Word, Google Docs, and most CMSes auto-curl by default. Curly quotes only count when stacked with other tells. +- **Em dashes alone.** Many editors and journalists use them often. Em dashes are evidence only when paired with formulaic sales-y rhythm. +- **One short emphatic sentence.** Humans use clipped sentences to land a point. Flag staccato drama only when several short fragments appear in a row and inflate the tone. +- **"Honestly" or "look" mid-sentence.** These are ordinary in casual writing. The tell is the standalone theatrical opener, not the word itself. +- **Unsourced claims.** Most of the web is unsourced. Lack of citations doesn't prove anything. +- **Correct, complex formatting.** Visual editors and templates produce clean output without any AI. +- **Secondhand text.** Do not rewrite watched phrases inside quotations, titles, proper names, or examples where the phrase is being discussed rather than used. -**After (Humanized):** -> The software update adds batch processing, keyboard shortcuts, and offline mode. Early feedback from beta testers has been positive, with most reporting faster task completion. +When in doubt, look for **clusters** of tells, not isolated ones. A single em dash means nothing; em dashes plus rule-of-three plus *vibrant tapestry* plus a "Conclusion" section is a confession. -**Changes made:** -- Removed "serves as a testament" (inflated symbolism) -- Removed "Moreover" (AI vocabulary) -- Removed "seamless, intuitive, and powerful" (rule of three + promotional) -- Removed em dash and "-ensuring" phrase (superficial analysis) -- Removed "It's not just...it's..." (negative parallelism) -- Removed "Industry experts believe" (vague attribution) -- Removed "pivotal role" and "evolving landscape" (AI vocabulary) -- Added specific features and concrete feedback +### Signs of human writing (preserve these) + +When you see these, lean toward leaving the prose alone — they are evidence of a real person writing, and over-editing will destroy what makes the piece sound human: + +- **Specific, unusual, hard-to-fabricate detail.** A real address. A weird quote. The phrase "the lawyer who used to work upstairs from my dentist." LLMs round off specifics; humans hoard them. +- **Mixed feelings and unresolved tension.** "I think this is mostly good, but it bothers me, and I can't fully explain why." LLMs default to clean takes. +- **Dated, era-bound references.** Slang, memes, or in-jokes that map to a specific year and subculture. Models lag by a year or more. +- **First-person editorial choices the writer can defend.** If the writer can explain *why* they made a particular cut or used a particular word, that's a strong human signal. +- **Variety in sentence length.** Real writing alternates short and long. AI writing tends toward an even, mid-length cadence. +- **Genuine asides, parentheticals, or self-corrections.** "(I keep wanting to say 'almost' here, but it really was certain.)" Models rarely interrupt themselves like this. +- **Edits made before November 30, 2022.** ChatGPT's public launch. Anything older than that is, with very rare exceptions, not AI-written. --- +## Invocation Modes + +**Pasted text (default).** The user gives text in the conversation. Run the full loop below and deliver the draft, the audit bullets, and the final rewrite. + +**File mode.** The user points at a file. Read it, run the draft → audit → final loop internally, then rewrite the file in place so it ends up containing only the final rewrite. Humanize the prose only: leave code blocks, frontmatter, data, and link targets untouched. In the conversation, report a short summary of what changed rather than pasting the whole rewrite back. + +**Embedded mode.** Another task or agent is using this skill as one step of a larger job (a PR description, a commit message, a doc). Run the loop internally and output only the final text. No draft, no audit bullets, no summary. The caller wants prose, not ceremony. + +## Process and Output + +1. Read the input carefully and identify every instance of the patterns above. +2. Write a **draft rewrite**. Check that it reads naturally aloud, varies sentence length, prefers specific details and simple constructions (is/are/has), and keeps the appropriate register. +3. Ask two questions: **"What makes the below so obviously AI generated?"** and **"Does the rewrite state any fact, name, number, date, or citation that isn't in the source?"** Answer briefly. A fabrication is a defect even when it sounds more human than the vague original. +4. Revise into a **final rewrite** that addresses them and contains no em or en dashes (see §14). + +In pasted-text mode, deliver the draft, the brief "still-AI" bullets, the final rewrite, and (optionally) a short summary of changes. In file and embedded modes, run the same loop but deliver only what the mode calls for (see Invocation Modes). + ## Public-facing copy -If the text is marketing copy, a landing page, product UI, or a social post, also run -the copy-specific tells in [references/copy-tells.md](references/copy-tells.md). Those -are ranked by a 3.2M-post analysis of what readers actually flag, and the top one (the -em dash) outranks every vocabulary word. +If the text is marketing copy, a landing page, product UI, or a social post, also run the copy-specific tells in [references/copy-tells.md](references/copy-tells.md). Those are ranked by a 3.2M-post Reddit analysis of what readers actually flag. -Deterministic scan for the mechanical subset: +Deterministic scan for the mechanical subset. `copy_scan.py` ships inside this skill, at `scripts/copy_scan.py` relative to this SKILL.md, so resolve it against this file's own directory: ```bash -python3 scripts/copy_scan.py # from the repo root +# user-level install +python3 ~/.claude/skills/humanizer/scripts/copy_scan.py +# project-level install +python3 .claude/skills/humanizer/scripts/copy_scan.py ``` +The scanner catches roughly the mechanical half; the cadence tells in that reference need your eyes. + ## This is pass 1 of 2 This skill fixes words, phrasing, and punctuation. It does not fix structure. -Structural tells survive a surface pass almost entirely intact: professional span-level -rewriting moved AI detection by only 1.6 points in the StoryScope study, while -structure alone detects AI text at 93.2% F1. After this pass, run -**`structural-humanizer`** for stated lessons, tidy arcs, embodied-emotion performance, -vague reference, and shape convergence. +Structural tells survive a surface pass almost intact: professional span-level rewriting moved AI detection by only 1.6 points in StoryScope, while structure alone detects AI text at 93.2% macro-F1. After this pass, run **`structural-humanizer`** for stated lessons, tidy arcs, embodied-emotion performance, vague reference, and shape convergence. Surface pass first, structural pass second. See `docs/PIPELINE.md`. diff --git a/skills/humanizer/references/copy-tells.md b/skills/humanizer/references/copy-tells.md index 1560cd9..c89e250 100644 --- a/skills/humanizer/references/copy-tells.md +++ b/skills/humanizer/references/copy-tells.md @@ -13,12 +13,20 @@ complaint posts. ## The mechanical four (a scanner can catch these) -Run `python3 scripts/copy_scan.py ` to flag them. +Run `scripts/copy_scan.py` (inside this skill) to flag them: +`python3 ~/.claude/skills/humanizer/scripts/copy_scan.py `. -### 1. The em dash (7.1%, the single most-cited writing tell) +### 1. The em dash (7.1%, the most-cited writing tell) -On visible copy the em dash reads as "a machine wrote this." It is the highest-signal -writing tell in the entire dataset, above any vocabulary word. +On visible copy the em dash reads as "a machine wrote this." It ranks above every +vocabulary word in the dataset. + +**Caveat from the source itself.** Four of that project's five auditors independently +confirmed the em dash as the most-cited tell in their chunks; the fifth argued the count +is inflated because most em-dash occurrences were the poster's own incidental +punctuation rather than a complaint about em dashes. The upstream synthesis kept it at #1 +and flagged the tension. Treat it as a strong signal, not a settled ranking, and note +that the en dash rides along with it (§14 of `SKILL.md` bans both). **Fix:** use a comma, a period, or parentheses. Do not simply substitute a colon, because readers flag that too as the same reflex wearing a different hat. 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*(\*|//|/\*|