@heyramzi/lint 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/bin/heyramzi-comment-length.js +4 -3
  2. package/bin/heyramzi-file-tokens.js +2 -2
  3. package/bin/heyramzi-slop.js +3 -1
  4. package/config/oxlintrc.json +1 -1
  5. package/data/slop/artifacts.js +87 -0
  6. package/data/slop/pattern-parts.js +56 -0
  7. package/data/slop/patterns/appositives-and-sayings.js +81 -0
  8. package/data/slop/patterns/comma-clauses.js +106 -0
  9. package/data/slop/patterns/diagram-and-script-tells.js +71 -0
  10. package/data/slop/patterns/dropped-elements.js +149 -0
  11. package/data/slop/patterns/duration-and-openers.js +102 -0
  12. package/data/slop/patterns/headings-and-laws.js +116 -0
  13. package/data/slop/patterns/numbers-and-runs.js +94 -0
  14. package/data/slop/patterns/openers-and-tails.js +90 -0
  15. package/data/slop/patterns/parallel-shapes.js +100 -0
  16. package/data/slop/patterns/reveals-and-tallies.js +101 -0
  17. package/data/slop/patterns/setups-and-closers.js +83 -0
  18. package/data/slop/patterns/subject-voice.js +67 -0
  19. package/data/slop/patterns/vague-and-flourish.js +102 -0
  20. package/data/slop/patterns/wikipedia-signs.js +103 -0
  21. package/data/slop/patterns.js +62 -0
  22. package/data/slop/phrases-en-closers.js +66 -0
  23. package/data/slop/phrases-en-core.js +185 -0
  24. package/data/slop/phrases-en-wikipedia.js +136 -0
  25. package/data/slop/phrases-fr.js +152 -0
  26. package/data/slop/shapes-density.js +81 -0
  27. package/data/slop/shapes-framing.js +101 -0
  28. package/data/slop/shapes-reveals.js +88 -0
  29. package/data/slop/title-tells.js +8 -0
  30. package/data/slop/words-en.js +178 -0
  31. package/data/slop/words-fr.js +101 -0
  32. package/data/slop-words.js +18 -2576
  33. package/data/vendor/heading-words.js +6 -0
  34. package/inline-path.js +2 -0
  35. package/package.json +1 -1
  36. package/slop.js +4 -2
  37. package/ui-rules.js +4 -2
@@ -18,826 +18,30 @@
18
18
  * Sourced from hardikpandya/stop-slop + local additions (EN + FR).
19
19
  */
20
20
 
21
- /** The English bans. Exported apart so an English-only surface can skip the French. */
22
- export const wordsEn = [
23
- // --- Existing workspace bans ---
24
- "foster",
25
- "fostering",
26
- "transformative",
27
- "navigating",
28
- "navigate",
29
- "seamless",
30
- "seamlessly",
31
- "unleash",
32
- "enhance",
33
- "enhancing",
34
- "embrace",
35
- "embracing",
36
- "ensure",
37
- "ensuring",
38
- "encourage",
39
- "encouraging",
40
- "continuous",
41
- "utilizing",
42
- "utilize",
43
- "comprehensive",
44
- "leveraging",
45
- "leverage",
46
- "enable",
47
- "enabling",
48
- "streamline",
49
- "streamlining",
50
- "efficiency",
51
- "versatile",
52
- "tailor",
53
- "tailored",
54
- "conduct",
55
-
56
- // --- Nominalised effort. The house word for the act is "following up". --- Measured 2026-08-16: zero occurrences across 56,568 words of first-party writing and speech.
57
-
58
- // "chase" survives once, as a plain verb inside "chase payment". The gerund is a copywriter's word, not his.
59
- "chasing",
60
-
61
- // --- 2026 corpus: the register words named repeatedly across 31 videos on AI writing, read 6 Sep 2026.
62
-
63
- // `quietly` and `amid` were each named by three independent sources as the fastest copy tells; the travel-brochure trio comes from the press-release voice a model defaults into when told to
64
-
65
- // be neutral. Evidence: humanizer/references/detection.md.
66
- "quietly",
67
- "amid",
68
- "commendable",
69
- "breathtaking",
70
- "scenic",
71
- "sleek",
72
-
73
- // --- Stop-slop: business jargon ---
74
- "actionable",
75
- "beacon",
76
- "bespoke",
77
- "bolster",
78
- "catalyst",
79
- "cornerstone",
80
- "curate",
81
- "curated",
82
- "delve",
83
- "delving",
84
- "disruptive",
85
- "ecosystem",
86
- "elevate",
87
- "elevating",
88
- "embark",
89
- "embarking",
90
- "empower",
91
- "empowering",
92
- "facilitate",
93
- "facilitating",
94
- "groundbreaking",
95
- "harness",
96
- "harnessing",
97
- "holistic",
98
- "innovative",
99
- "intricate",
100
- "intricacies",
101
- "landscape",
102
- "meticulous",
103
- "meticulously",
104
- "multifaceted",
105
- "myriad",
106
- "nuanced",
107
- "optimize",
108
- "optimizing",
109
- "paramount",
110
- "paradigm",
111
- "pivotal",
112
- "payoff",
113
- "plethora",
114
- "poised",
115
- "realm",
116
- "redefine",
117
- "redefining",
118
- "reimagine",
119
- "reimagining",
120
- "reshape",
121
- "reshaping",
122
- "revolutionize",
123
- "revolutionizing",
124
- "robust",
125
- "scalable",
126
- "spearhead",
127
- "synergy",
128
- "tapestry",
129
- "testament",
130
- "underpin",
131
- "underscore",
132
- "unpack",
133
- "unpacking",
134
-
135
- // --- Stop-slop: adverbs (AI tells) ---
136
- "crucially",
137
- "deeply",
138
- "fundamentally",
139
- "furthermore",
140
- "genuinely",
141
- "importantly",
142
- "inevitably",
143
- "inherently",
144
- "interestingly",
145
- "moreover",
146
- "truly",
147
- "ultimately",
148
-
149
- // --- petergyang/no-ai-slop, read 2026-08-31 --- The six surface forms that list carries and this one did not.
150
-
151
- // The word list already bans "underscore", "paradigm", "testament" and "pivotal", but \b matching lets the plural and the gerund through, which is how "underscores its significance" reads clean.
152
-
153
- // "highlighting" and "reflecting" are deliberately absent: both are ordinary English, so the trailing -ing analysis clause stays a human read against patterns.md 3.
154
-
155
- // Zero occurrences of all six across the first-party corpus.
156
- "showcasing",
157
- "underscores",
158
- "underscoring",
159
- "supercharge",
160
- "supercharging",
161
- "ever-evolving",
162
-
163
- // --- Wikipedia:Signs of AI writing, "AI vocabulary", read 2026-09-05 --- The words-to-watch that list carries and this one did not.
164
-
165
- // "highlight" and "key" are deliberately absent: both are ordinary English, and the shape they appear in is caught by the `superficial-ing-clause` pattern instead. Sources: WP:AIVOCAB, WP:AIPUFFERY, WP:AILEGACY.
166
- "additionally",
167
- "boast",
168
- "boasts",
169
- "bolstered",
170
- "cementing",
171
- "crucial",
172
- "cultivating",
173
- "emphasizing",
174
- "emphasises",
175
- "emphasizes",
176
- "encompassing",
177
- "enduring",
178
- "epitomizes",
179
- "exemplifies",
180
- "exemplifying",
181
- "garner",
182
- "garnered",
183
- "garnering",
184
- "interplay",
185
- "nestled",
186
- "profound",
187
- "renowned",
188
- "resonate",
189
- "resonates",
190
- "showcase",
191
- "showcases",
192
- "solidifying",
193
- "symbolizing",
194
- "underpinning",
195
- "underpins",
196
- "valuable",
197
- "vibrant",
198
- ];
199
-
200
- /** The French bans. Same lists, French surface forms. */
201
- export const wordsFr = [
202
- // --- French: business jargon ---
203
- "optimiser",
204
- "valoriser",
205
- "accompagner",
206
- "accompagnement",
207
- "performant",
208
- "performante",
209
- "incontournable",
210
- "levier",
211
- "leviers",
212
- "piloter",
213
- "pilotage",
214
- "pérenniser",
215
- "structurer",
216
- "structurant",
217
- "structurante",
218
- "fédérer",
219
- "dynamiser",
220
- "dynamique",
221
- "transversal",
222
- "transversale",
223
- "mutualiser",
224
- "capitaliser",
225
- "prioriser",
226
- "sécuriser",
227
- "fiabiliser",
228
- "fluidifier",
229
- "harmoniser",
230
- "rationaliser",
231
- "déployer",
232
-
233
- // --- French: AI filler adverbs ---
234
- "véritablement",
235
- "fondamentalement",
236
- "indéniablement",
237
- "assurément",
238
- "indubitablement",
239
- "intrinsèquement",
240
- "indiscutablement",
241
-
242
- // --- French: AI buzzwords ---
243
- "holistique",
244
- "exhaustif",
245
- "exhaustive",
246
- "paradigme",
247
- "écosystème",
248
- "synergie",
249
- "innovant",
250
- "innovante",
251
- "disruptif",
252
- // "disruptive" is the French feminine and the English adjective; it is listed
253
- // once in the English block above, and a second entry only duplicated it.
254
- "résilient",
255
- "résiliente",
256
- "résilience",
257
- "proactif",
258
- "proactive",
259
- "pérenne",
260
- "sur-mesure",
261
-
262
- // --- French: the same signs, in French --- fr:Aide:Identifier l'usage d'une IA générative, read 2026-09-05.
21
+ /*
22
+ * The lists live beside this file in `data/slop/`, one file per job. This module assembles `words`, `phrasesEn`, `phrases` and `shapes`, renders the prompt blocks, and is the published `@heyramzi/lint/slop-words` surface.
23
+ */
263
24
 
264
- // It names "ton promotionnel", "langue de bois" and "emphase excessive" without listing words, so these are the French surface forms of the English words above:
25
+ import { artifacts } from "#lint/data/slop/artifacts.js";
26
+ import { patterns } from "#lint/data/slop/patterns.js";
27
+ import { phrasesEnClosers } from "#lint/data/slop/phrases-en-closers.js";
28
+ import { phrasesEnCore } from "#lint/data/slop/phrases-en-core.js";
29
+ import { phrasesEnWikipedia } from "#lint/data/slop/phrases-en-wikipedia.js";
30
+ import { phrasesFr } from "#lint/data/slop/phrases-fr.js";
31
+ import { shapesDensity } from "#lint/data/slop/shapes-density.js";
32
+ import { shapesFraming } from "#lint/data/slop/shapes-framing.js";
33
+ import { shapesReveals } from "#lint/data/slop/shapes-reveals.js";
34
+ import { titleTells } from "#lint/data/slop/title-tells.js";
35
+ import { wordsEn } from "#lint/data/slop/words-en.js";
36
+ import { wordsFr } from "#lint/data/slop/words-fr.js";
265
37
 
266
- // the puffery adjectives, the calques of underscore/showcase, and the participles the superficial-analysis clause hangs on.
267
- "emblématique",
268
- "renommé",
269
- "renommée",
270
- "prisé",
271
- "prisée",
272
- "foisonnant",
273
- "foisonnante",
274
- "niché",
275
- "nichée",
276
- // "vibrant" and "crucial" carry the same spelling in both languages and are
277
- // listed once, in the English block. Only the feminine forms need an entry.
278
- "vibrante",
279
- "cruciale",
280
- "primordial",
281
- "primordiale",
282
- "jalon",
283
- "fleuron",
284
- "florissant",
285
- "florissante",
286
- "inestimable",
287
- "soulignant",
288
- // "mettant" is deliberately absent: "mettant en place" is ordinary French.
289
- // Its slop forms are phrases, "mettant en lumière" and "mettant en avant".
290
- "témoignant",
291
- "illustrant",
292
- "reflétant",
293
- "renforçant",
294
- "consacrant",
295
- "conjuguer",
296
- "insuffler",
297
- "impulser",
298
- "plébiscité",
299
- "plébiscitée",
300
- ];
38
+ export { artifacts, patterns, phrasesFr, titleTells, wordsEn, wordsFr };
301
39
 
302
40
  /** Every banned word, both languages. The list every consumer read before the split. */
303
41
  export const words = [...wordsEn, ...wordsFr];
304
42
 
305
43
  /** The English banned phrases. */
306
- export const phrasesEn = [
307
- // --- Existing workspace bans ---
308
- "not only",
309
- "but also",
310
-
311
- // --- Negation pivots: the "it is not X, it is Y" reveal --- Substring-matched, so only distinctive multi-word forms belong here.
312
-
313
- // A bare "is not" is normal English and must never be listed.
314
- "it's not just",
315
- "it is not just",
316
- "not just about",
317
- "it's not about",
318
- "it is not about",
319
- "isn't about",
320
- "it's not merely",
321
- "it is not merely",
322
- "not merely a",
323
- "this isn't just",
324
- "this is not just",
325
- "that's not just",
326
- "more than just a",
327
- "ce n'est pas seulement",
328
- "il ne s'agit pas seulement",
329
- "non seulement",
330
- "ever wondered why",
331
- "reach new heights",
332
- "in the realm of",
333
- "think of it as",
334
- "that's a wrap",
335
- "it's like",
336
- "let's dive in",
337
- "dive in",
338
- "buckle up",
339
- "to the next level",
340
- "in the fast-paced",
341
- "in today's",
342
- "hidden gems",
343
-
344
- // --- Stop-slop: throat-clearing openers ---
345
- "here's the thing",
346
- "the uncomfortable truth",
347
- "it turns out",
348
- "let me be clear",
349
- "the truth is",
350
- "can we talk about",
351
- "here's what i find",
352
- "here's the problem",
353
- "i'll say it again",
354
- "i'm going to be honest",
355
-
356
- // --- 2026 corpus: the three "here's the X" openers named alongside the two above by copy and marketing sources.
357
-
358
- // Same shape, same job, and the copy one was caught in a shipped email arguing against AI writing.
359
- "here's the fix",
360
- "here's the kicker",
361
- "here's the gap",
362
-
363
- // --- Transition crutches.
364
-
365
- // Held only in prose until 3 Sep 2026, in a "Transitions to Avoid" list inside seo-copywriting, where nothing checked them: 7 of its 10 entries were already here and 3
366
-
367
- // were not, so the file was both a duplicate and the only home for the rest. ---
368
- "that being said",
369
- "this begs the question",
370
- "let's delve into",
371
- "lets delve into",
372
-
373
- // --- Stop-slop: emphasis crutches ---
374
- "let that sink in",
375
- "this matters because",
376
- "make no mistake",
377
- "here's why that matters",
378
-
379
- // --- Stop-slop: business jargon phrases ---
380
- "lean into",
381
- "double down",
382
- "deep dive",
383
- "take a step back",
384
- "moving forward",
385
- "circle back",
386
- "on the same page",
387
- "game-changer",
388
- "game changer",
389
- "cutting-edge",
390
- "cutting edge",
391
- "best-in-class",
392
- "best in class",
393
- "next-generation",
394
- "state-of-the-art",
395
- "end-to-end",
396
-
397
- // --- Stop-slop: filler phrases ---
398
- "no more",
399
- "say goodbye to",
400
- "at its core",
401
- "at the end of the day",
402
- "in a world where",
403
- "in conclusion",
404
- "it's worth noting",
405
- "rest assured",
406
- "the reality is",
407
- "when it comes to",
408
-
409
- // --- Stylometric markers from guillaumemeyer/watermarks-remover --- Its detector scores 24 weighted markers.
410
-
411
- // 26 of the 34 surface forms those cover were already banned here; these are the eight that were not, checked against 56,568 words of first-party corpus first so none of
412
-
413
- // them is his. Read 2026-08-16.
414
- "it is important to note",
415
- "it is essential to note",
416
- "it is crucial to note",
417
- "it is worth noting",
418
- "to summarize",
419
- "plays a crucial role",
420
- "plays a key role",
421
- "plays a vital role",
422
-
423
- // --- Assistant leakage: a chatbot's own turn-taking, left in the copy ---
424
- "as an ai",
425
- "i hope this helps",
426
-
427
- // --- Stop-slop: meta-commentary ---
428
- "plot twist",
429
- "you already know this",
430
- "is a feature, not a bug",
431
- "let me walk you through",
432
- "as we'll see",
433
-
434
- // --- The unfinished list, and the writer narrating his own argument --- Read from a Nicolas Cole newsletter on 26 Aug 2026, a specimen of the creator-newsletter register.
435
-
436
- // "the list goes on and on" closes two separate lists in it, both times in place of the items the writer did not have.
437
-
438
- // Zero occurrences in Ramzi's corpus for all of these except "possibilities are endless", which appears once, in a 2025 ClickUp post from the generic marketer era this voice system was
439
-
440
- // built to end.
441
- "the list goes on",
442
- "the list is endless",
443
- "possibilities are endless",
444
- "and so much more",
445
- "my point is",
446
- "so you see",
447
- "half the battle",
448
- "the name of the game",
449
-
450
- // --- Stop-slop: vague declaratives ---
451
- "the implications are",
452
- "the stakes are high",
453
- "the consequences are",
454
- "the reasons are structural",
455
-
456
- // --- petergyang/no-ai-slop, read 2026-08-31 --- Faux-insight setups, weasel attribution, rhetorical setups, reader guidance and dated-world filler.
457
-
458
- // Every one is a distinctive multi-word form, so it can be substring-matched without firing on ordinary English; the ones that cannot ("in other words",
459
-
460
- // "literally", "simply", "overall") stay judgement calls in patterns.md 48. Zero occurrences across the first-party corpus.
461
- "this changes everything",
462
- "this is huge",
463
- // "in today's" is listed above; only the curly apostrophe needs its own entry.
464
- "in today\u2019s",
465
- "in the age of",
466
- "in the world of",
467
- "in this article",
468
- "going forward",
469
- "with regard to",
470
- "in terms of",
471
- "widely regarded as",
472
- "experts agree",
473
- "industry reports suggest",
474
- "many argue",
475
- "what if i told you",
476
- // "think about it" is NOT listed: the slop form is the standalone imperative ("Think about it:"), and a substring ban also catches the ordinary subordinate clause,
477
-
478
- // which shipped copy uses ("whether you think about it or not"). It stays in patterns.md 33 as a human read.
479
-
480
- // "as you can see" is NOT listed: voice-measured.md measures it 20 times in his own spoken corpus, tagged "spoken only, needs a screen".
481
-
482
- // It is his tutorial register pointing at a screen, not reader guidance. patterns.md 48 carries it as a written-copy read.
483
- "the key point is",
484
- "this distinction matters",
485
- "nobody tells you",
486
- "the part everyone misses",
487
- "most people get wrong",
488
- "most people skip",
489
-
490
- // --- Wikipedia:Signs of AI writing, read 2026-09-05 --- One block per section of that page, so a reader can trace a ban back to the sign it came from.
491
-
492
- // Only distinctive multi-word forms are here; the signs that need an anchor are `patterns` below, and the ones that need a whole document are the structural checks in `slop.js`.
493
-
494
- // WP:AILEGACY, WP:AITREND. Significance asserted instead of stated.
495
- "a testament to",
496
- "plays a significant role",
497
- "plays a pivotal role",
498
- "a pivotal moment",
499
- "a key turning point",
500
- // "serves as a", "stands as a", "marks a shift" and "represents a shift" are not listed here: the `copula-avoidance` pattern below owns that whole family,
501
-
502
- // and a phrase entry would only report the same sentence twice.
503
- "reflects a broader",
504
- "reflects broader",
505
- "part of a broader",
506
- "setting the stage for",
507
- "indelible mark",
508
- "deeply rooted",
509
- "evolving landscape",
510
- "focal point",
511
- "underscores the importance",
512
- "highlights the importance",
513
- "emphasizes the importance",
514
- "underscoring its significance",
515
- "contributing to the broader",
516
- "in the broader context",
517
- "ongoing efforts to",
518
-
519
- // WP:OVERATTRIBUTION, WP:AIATTR. Notability asserted instead of shown.
520
- "independent coverage",
521
- "media outlets",
522
- "trade publications",
523
- "widely read outlets",
524
- "has been profiled in",
525
- "has been featured in",
526
- "active social media presence",
527
- "significant coverage",
528
- "substantial coverage",
529
- "independent and reliable sources",
530
-
531
- // WP:AIPUFFERY, WP:AIPEACOCK. The travel-guide register.
532
- "rich cultural heritage",
533
- "rich history",
534
- "natural beauty",
535
- "in the heart of",
536
- "nestled in",
537
- "nestled within",
538
- "diverse array",
539
- "wide array of",
540
- "a wide range of",
541
- "commitment to excellence",
542
- "a fascinating glimpse",
543
- "a glimpse into",
544
- "shed light on",
545
- "valuable insights",
546
- "align with",
547
- "aligns with",
548
- "resonate with",
549
- "resonates with",
550
- "an integral part of",
551
-
552
- // WP:FACESCHALLENGES. The formulaic closing section.
553
- "faces several challenges",
554
- "faces a number of challenges",
555
- "despite these challenges",
556
- "despite its challenges",
557
- "challenges and opportunities",
558
- "future prospects",
559
- "future outlook",
560
- "awards and recognition",
561
- "recognition and awards",
562
-
563
- // WP:CONCLUSION, WP:INCONCLUSION. The section summary. "in conclusion" is
564
- // listed above with the filler phrases.
565
- "in summary",
566
- "to sum up",
567
-
568
- // WP:DIDACTIC. The disclaimer aimed at an imagined reader.
569
-
570
- // The uncontracted "it is important/essential/crucial to note" and "it's worth noting" are listed above; these are the forms a substring match on those misses.
571
- "it's important to note",
572
- "it's essential to note",
573
- "it's crucial to note",
574
- "important to remember",
575
- "crucial to remember",
576
- "worth remembering",
577
- "important to consider",
578
- "may vary depending",
579
-
580
- // WP:CERTAINLY, WP:COLLABCOMM. The chatbot's own turn, left in the copy.
581
- // "as an ai" and "i hope this helps" are listed above.
582
- "as an ai language model",
583
- "as a large language model",
584
- "i cannot provide",
585
- "i'm sorry, but",
586
- "i am sorry, but",
587
- "you're absolutely right",
588
- "you are absolutely right",
589
- "great question",
590
- "would you like me to",
591
- "let me know if you",
592
- "is there anything else",
593
- "detailed breakdown",
594
- "here is a breakdown",
595
- "here's a breakdown",
596
- "i hope this message finds you well",
597
- "i hope this finds you well",
598
- "feel free to reach out",
599
-
600
- // WP:AICUTOFF, WP:AIDISCLAIMER. The model speculating about its own gaps.
601
- "as of my last knowledge update",
602
- "as of my last training update",
603
- "up to my last training update",
604
- "based on available information",
605
- "based on the available information",
606
- "while specific details are limited",
607
- "specific details are scarce",
608
- "not widely documented",
609
- "not widely available",
610
- "not publicly available",
611
- "in the provided sources",
612
- "in the available sources",
613
- "in the search results",
614
- "maintains a low profile",
615
- "keeps personal details private",
616
-
617
- // WP:AICONNECT, WP:AIASSOCIATION. A relationship alluded to, never stated.
618
- "widely interpreted as",
619
- "has been associated with",
620
- "widely associated with",
621
- "in connection with",
622
- "in association with",
623
-
624
- // --- blader/humanizer 3.0.0 catch-up, 21 Sep 2026. Only the distinctive multi-word forms; upstream's bare "linked to", "tied to" and "of course" are ordinary English and stay out.
625
-
626
- // --- Pause-for-effect closers and sayings that sound deep.
627
- "read that again",
628
- "that's the real win",
629
- "that is the real win",
630
- "the real question is",
631
- "what really matters",
632
- "the deeper issue",
633
- "the heart of the matter",
634
- // Staged run-ups before the point.
635
- "let's explore",
636
- "let's break this down",
637
- "here's what you need to know",
638
- "now let's look at",
639
- "without further ado",
640
- "let's be honest",
641
- "real talk",
642
- // Arguing with no one, and the fake alternative.
643
- "i'm not saying",
644
- "to be clear",
645
- "don't get me wrong",
646
- "this is not to say",
647
- "a tempting approach",
648
- "one might be tempted",
649
- "it would be easy to just",
650
- // Stacked qualifiers.
651
- "could potentially",
652
- "might arguably",
653
- "this is an inference",
654
- // Send-off inflation and sales language.
655
- "the future looks bright",
656
- "exciting times ahead",
657
- "a step in the right direction",
658
- "must-visit",
659
- "active social media presence",
660
- "several publications",
661
- // Chatbot residue and guesses passed off as fact.
662
- "should i continue",
663
- "it is believed that",
664
-
665
- // --- First-person softeners.
666
-
667
- // Ramzi, 21 Sep 2026: "we need to speak with a little bit more confidence and assertiveness, like removing I think and please." He dictates them to Claude 1.8 times per
668
-
669
- // 1,000 words; in copy they are hedges. Bare "please" stays out: error and legal microcopy needs it. ---
670
- "i think",
671
- "i believe",
672
- "in my opinion",
673
- "i guess",
674
- "i suppose",
675
- "i feel like",
676
- "i'd say",
677
- "i would say",
678
- "i'm not sure",
679
- "i was wondering",
680
- "just wanted to",
681
- "if that makes sense",
682
- "hopefully",
683
- "please feel free",
684
- "please don't hesitate",
685
- "please note that",
686
- "please be aware",
687
- ];
688
-
689
- /** The French banned phrases. */
690
- export const phrasesFr = [
691
- // --- French: throat-clearing openers ---
692
- "il est important de noter",
693
- "il convient de souligner",
694
- "il est essentiel de",
695
- "force est de constater",
696
- "il va sans dire",
697
- "dans un monde où",
698
- "à l'ère du",
699
- "à l'heure où",
700
- "dans le paysage actuel",
701
-
702
- // --- French: filler phrases ---
703
- "en fin de compte",
704
- "au bout du compte",
705
- "en d'autres termes",
706
- "il est à noter que",
707
- "cela étant dit",
708
- "dans cette optique",
709
- "à cet égard",
710
- "en ce qui concerne",
711
- "dans le cadre de",
712
-
713
- // --- French: business jargon phrases ---
714
- "mise en place",
715
- "montée en compétence",
716
- "montée en puissance",
717
- "retour sur investissement",
718
- "valeur ajoutée",
719
- "prise en compte",
720
- "conduite du changement",
721
- "transformation digitale",
722
- "transformation numérique",
723
- "passage à l'échelle",
724
- "de pointe",
725
- "clé en main",
726
- "sur mesure",
727
- "de bout en bout",
728
- "à la pointe",
729
- "état de l'art",
730
-
731
- // --- French: AI emphasis crutches ---
732
- "il ne fait aucun doute",
733
- "sans aucun doute",
734
- "il est indéniable",
735
- "de manière significative",
736
- "de façon significative",
737
- "tout au long de",
738
-
739
- // --- French: the same Wikipedia signs, in French --- fr:Aide:Identifier l'usage d'une IA générative, read 2026-09-05, plus the French surface forms of the English blocks above.
740
-
741
- // The French page adds no sign the English one lacks except its emphasis on "langue de bois", so the blocks below mirror the English ones section for section.
742
-
743
- // Significance asserted instead of stated.
744
- "constitue un témoignage",
745
- "témoigne de l'importance",
746
- "s'impose comme",
747
- "se présente comme",
748
- "joue un rôle crucial",
749
- "joue un rôle clé",
750
- "joue un rôle majeur",
751
- "joue un rôle central",
752
- "un tournant décisif",
753
- "un moment charnière",
754
- "une étape clé",
755
- "marque un tournant",
756
- "reflète une tendance",
757
- "s'inscrit dans une dynamique",
758
- "s'inscrit dans un contexte",
759
- "contribuant ainsi",
760
- "mettant en lumière",
761
- "mettant en avant",
762
- "met en lumière",
763
- "met en évidence",
764
- "souligne l'importance",
765
- "soulignant l'importance",
766
-
767
- // Notability asserted instead of shown.
768
- "sources fiables et indépendantes",
769
- "de nombreux médias",
770
- "largement relayé",
771
- "largement médiatisé",
772
- "présence active sur les réseaux",
773
-
774
- // The travel-guide register.
775
- "au cœur de",
776
- "niché au cœur",
777
- "riche patrimoine",
778
- "patrimoine culturel riche",
779
- "beauté naturelle",
780
- "un large éventail",
781
- "une large gamme",
782
- "un aperçu fascinant",
783
- "des informations précieuses",
784
- "en résonance avec",
785
-
786
- // The formulaic closing section.
787
- "malgré ces défis",
788
- "malgré ces obstacles",
789
- "fait face à plusieurs défis",
790
- "de nombreux défis",
791
- "défis et perspectives",
792
- "perspectives d'avenir",
793
- "prix et distinctions",
794
-
795
- // The section summary.
796
- "en résumé",
797
- "pour résumer",
798
- "en somme",
799
- "pour conclure",
800
-
801
- // The disclaimer aimed at an imagined reader.
802
- "il est crucial de",
803
- "il est primordial de",
804
- "il est intéressant de noter",
805
- "il est bon de noter",
806
- "il convient de noter",
807
- "il est utile de rappeler",
808
- "peut varier selon",
809
-
810
- // The chatbot's own turn, left in the copy.
811
- "en tant qu'ia",
812
- "en tant que modèle de langage",
813
- "je ne peux pas fournir",
814
- "je suis désolé, mais",
815
- "vous avez tout à fait raison",
816
- "excellente question",
817
- "souhaitez-vous que je",
818
- "y a-t-il autre chose",
819
- "voici un aperçu détaillé",
820
- "voici une version",
821
- "j'espère que cela vous aidera",
822
- "n'hésitez pas à me solliciter",
823
-
824
- // The model speculating about its own gaps.
825
- "à ma dernière mise à jour",
826
- "selon les informations disponibles",
827
- "d'après les informations disponibles",
828
- "les détails sont limités",
829
- "peu de sources",
830
- "n'est pas largement documenté",
831
- "n'est pas publiquement disponible",
832
-
833
- // A relationship alluded to, never stated.
834
- "en lien avec",
835
- "en association avec",
836
- "largement associé",
837
- "étroitement associé",
838
- "souvent associé",
839
- "largement interprété comme",
840
- ];
44
+ export const phrasesEn = [...phrasesEnCore, ...phrasesEnWikipedia, ...phrasesEnClosers];
841
45
 
842
46
  /** Every banned phrase, both languages. */
843
47
  export const phrases = [...phrasesEn, ...phrasesFr];
@@ -857,1769 +61,7 @@ export const phrases = [...phrasesEn, ...phrasesFr];
857
61
  /*
858
62
  * `example` is the shape written out, so a model has something to match against.
859
63
  */
860
- export const shapes = [
861
- {
862
- id: "negation-pivot",
863
- name: "Negation pivot",
864
- rule: 'Defining a thing by first denying a different thing. Banned outright in written copy; at most one per spoken script. State what the thing is and let the contrast be implied. The comma form, "X, not the Y", is decidable and fails the gate as `comma-not-pivot`.',
865
- example:
866
- '"It is not a project, it is a wish." / "X does not happen. Y happens." / "The problem is not X, it is Y." / "None of it does X. It just does Y."',
867
- },
868
- {
869
- id: "deadpan-closer",
870
- name: "Deadpan closer",
871
- rule: "A short flat declarative parked at the end of a block to land the point. One is a writer's choice. The tell is that every block on the page ends the same way, so the reader can predict the last sentence before reading it, and the page acquires one rhythm. Count them per page rather than per paragraph: #31 catches a run inside one paragraph and this is a run across a page. Fix by ending some blocks mid-thought, some on the long sentence, and some on the fact rather than the verdict.",
872
- example:
873
- '"You picked a template one Sunday and got as far as the header. The About page is still empty." / "There is no project to manage." / "Nothing has been charged."',
874
- },
875
- {
876
- id: "promised-outcome-as-fact",
877
- name: "Promised outcome stated as fact",
878
- rule: 'A result that has not happened yet, and may never happen, written in the plain present as if it were already true. The reader knows it is not true today, so the sentence reads as a claim nobody could back, and the whole page loses its footing. It comes from copying a feature bullet ("Syncs every hour") onto an outcome the product cannot control: whether customers call, whether Google ranks, whether an assistant names you. Ramzi, 17 Sep 2026, on "Customers reach you on your phone": we are "pretending the truth". Say what is possible, or what we do: "Customers can reach you on your phone", "We build the page Google reads". Keep the plain present only for what is already true of the thing in front of the reader.',
879
- example:
880
- '"Customers reach you on your phone" / "People in your town find you on Google" / "ChatGPT names you when somebody asks" / "Clients pay on time"',
881
- },
882
- {
883
- id: "self-acting-abstraction",
884
- name: "Self-acting abstraction",
885
- rule: 'An inanimate subject given an agentive verb, so nobody does the work and no mechanism is named. The reflexive form is the loud one ("the week plans itself"), and the quiet one is the same fault without the reflexive: a tool, a document or a schedule as the subject of a verb only a person or a program performs. Ramzi, 7 Sep 2026: "XX that XX themselves", and 17 Sep 2026 on "A calendar takes them": the subject is an abstraction. Unlintable because the identical grammar is correct when the subject really is the actor ("the script reads the file"), so it is judged on whether the named subject can do the named thing. Name the actor and the mechanism: what reads the call, what writes the task.',
886
- example:
887
- '"Tasks that write themselves" / "The week plans itself" / "A calendar takes them" / "Calls become task updates on their own" / "a workspace that runs itself"',
888
- },
889
- {
890
- id: "comma-hung-fragment",
891
- name: "Comma-hung fragment",
892
- rule: 'A noun, a comma, then a fragment with no verb of its own, usually a past participle or a bare adverb. Ramzi, 7 Sep 2026, on three of them: "xxx, XXXed ai slop" and "XXX, XXX in such sentence is ai slop". His comma joins a list of three or more, an adverbial opener, or two clauses that each have a subject and a verb. Nothing else. Write the sentence: "the report is filed", "you get 4 hours of your week back".',
893
- example:
894
- '"Sales tax report, filed" / "The week, planned" / "4 to 5 hours a week, back" / "One line, nothing dramatic"',
895
- },
896
- {
897
- id: "correlative-inflation",
898
- name: "Correlative inflation",
899
- rule: "Stacked correlative pairs used to make one idea sound like two.",
900
- example: '"not only X but also Y" / "both X and Y" where only X is doing work',
901
- },
902
- {
903
- id: "rule-of-three",
904
- name: "Rule of three",
905
- rule: "Three-item lists where the third item exists only for rhythm. Cut it or make it load-bearing.",
906
- example: '"faster, cleaner, and more reliable"',
907
- },
908
- {
909
- id: "superficial-ing-analysis",
910
- name: "Superficial -ing analysis",
911
- rule: "A trailing participial clause that restates the sentence as significance instead of adding a fact.",
912
- example: '"..., highlighting the importance of clear processes."',
913
- },
914
- {
915
- id: "engagement-bait-close",
916
- name: "Engagement-bait close",
917
- rule: "A question bolted onto the end with no real offer behind it. End on the idea, or on one specific real ask.",
918
- example: '"What do you think?" / "How do you handle this? Let me know below."',
919
- },
920
- {
921
- id: "selfish-framing",
922
- name: "Selfish framing",
923
- rule: 'Copy about the writer instead of the reader. Count "I", "we", "my", "our", "mine", "ours" against "you", "your"; second person has to win. First person is for evidence the author measured or did, never for positioning. A bare possessive pronoun standing alone as a subject ("Mine is day 21.") is the worst form of it: the sentence exists to announce that the writer has one.',
924
- example: '"We are excited to share our new approach." / "Mine is day 21."',
925
- },
926
- {
927
- id: "dramatized-pain",
928
- name: "Dramatized pain",
929
- rule: "Inflating the reader's problem past what they would call it themselves.",
930
- example: '"operational nightmare" / "a complete disaster"',
931
- },
932
- {
933
- id: "the-part-nobody",
934
- name: "The unclaimed-insight preamble",
935
- rule: "Announcing that what follows is the overlooked part, instead of just saying it. The writer awards themselves the insight before the reader has judged it, and the sentence carries no information. Delete the preamble and keep the point.",
936
- example:
937
- '"The part nobody raised: charge for it." / "What everyone misses here is X." / "The thing nobody talks about:" / "Here is what they will not tell you."',
938
- },
939
- {
940
- id: "nobody-universal",
941
- name: "The invented universal",
942
- rule: 'A claim that nobody does the thing, stated as fact to make an ordinary point sound like a discovery. It is unprovable and almost never true, and the reader knows it. Ramzi, 23 Sep 2026, on "and nobody writes it down": "Nobody XXX is AI slop." Unlintable because "nobody will read that" is a real verdict on a real card. Name who, where, and what it costs them: "the team keeps the steps in their heads, so a new hire asks the same thing twice".',
943
- example:
944
- '"and nobody writes it down" / "Nobody checks the numbers." / "Nobody reads the handbook." / "Everyone does it, and nobody measures it."',
945
- },
946
- {
947
- id: "tells-you-more-than",
948
- name: "The diagnostic-tell close",
949
- rule: "Closing by ranking one signal above another as a source of truth. It sounds like earned judgement and is untestable, and it always arrives as the last line so it reads as a moral.",
950
- example:
951
- '"How they answer tells you more than the brief does." / "Their reply says more than the contract ever will." / "That one question reveals more than an hour of discovery."',
952
- },
953
- {
954
- id: "chiastic-reveal",
955
- name: "Chiastic reveal",
956
- rule: "Two abstract nouns swapped across a colon or a full stop so the sentence sounds like an insight. It is a rhetorical figure with no content: the reader has to decode the wordplay before reaching the point, and nobody speaks this way. Say the point.",
957
- example:
958
- '"Everyone here has the where. The part that took me longest was the what." / "The problem was never the tool. It was the habit." / "You do not need more time. You need less work."',
959
- },
960
- {
961
- id: "appositive-fragment",
962
- name: "Appositive fragment",
963
- rule: "A noun phrase, a comma, then a verbless phrase that grades or denies the first half. The second half carries no fact, only the writer's assurance about the tone of the first. A comma in a short sentence is allowed to join a list of three or more real objects, an adverbial opener, or two clauses that each have a subject and a verb. Nothing else. Delete the appositive, or give it a verb.",
964
- example:
965
- '"One line, nothing dramatic." / "A single question, no pressure." / "Two fields, nothing fancy."',
966
- },
967
- {
968
- id: "imperative-payoff",
969
- name: "Imperative with a restated payoff",
970
- rule: 'An order to the reader whose payoff only restates the order: the reader is told to do something and then told what they would have seen, so the line teaches nothing and orders nothing. Ramzi, 8 Sep 2026, on a shipped course title slide. Write the claim as a plain statement, or make the imperative an instruction somebody can carry out. Stays out of `patterns` because the same shape is right in a tutorial step: "Run pnpm dev and you get a server on 5173".',
971
- example:
972
- '"Open 10 agency accounts and you get 10 shapes" / "Fix the shape and the fields can be fixed too" / "Ask 3 people and you get 3 answers"',
973
- },
974
- {
975
- id: "moral-aphorism",
976
- name: "Moral aphorism",
977
- rule: "An abstract virtue or vice given a predicate as a general truth about people. It reads as a lesson delivered from above, and it is unfalsifiable, so it adds nothing the surrounding sentence did not already carry. Generalisations take a concrete subject out of the work: a tool, a price, a status, a deadline.",
978
- example:
979
- '"Politeness is free, so it gets treated as free." / "Trust is earned in drops." / "Urgency is a choice."',
980
- },
981
- {
982
- id: "definitional-demotion",
983
- name: "Definitional demotion",
984
- rule: 'A concrete noun, a relative clause that disqualifies it, then an equals sign to a lesser noun: "A backup nobody has rebuilt from is a folder." The shape reads as a hard-won definition and is a word game. Nothing is measured, nothing is instructed, and the reader cannot act on the verdict. Write the mechanism instead: what the thing fails to do, and what to do about it. It is the positive twin of the negation pivot, so a draft that has had its "it is not X, it is Y" removed often grows this one in its place.',
985
- example:
986
- '"A backup nobody has rebuilt from is a folder." / "A process nobody follows is a document." / "A plan without a date is a wish." / "A meeting with no notes is a rumour."',
987
- },
988
- {
989
- id: "hypothetical-law",
990
- name: "Hypothetical law",
991
- rule: 'An "if" clause followed by a re-labelling of an abstraction rather than by an instruction or a real consequence. The sentence sounds like a discovered rule and is only a restatement. Follow a conditional with what to do, or with what actually happens.',
992
- example:
993
- '"If nothing ever stops, your due date is a suggestion." / "If everything is urgent, nothing is." / "If you never say no, your calendar belongs to somebody else."',
994
- },
995
- {
996
- id: "colon-connector",
997
- name: "Colon as a connector",
998
- rule: "A colon used mid-sentence to join two clauses that a full stop would join better. A colon is right before a list or an example and nowhere else. The construction always arrives with comparison framing in front of it, so the fix is to drop both and let the point stand on its own.",
999
- example:
1000
- '"If you are coming from traditional automation: instead of registering handlers, you describe conditions." / "The rule is simple: write it down." / "Here is the tradeoff: speed against accuracy."',
1001
- },
1002
- {
1003
- id: "abstract-metaphor-noun",
1004
- name: "Abstract metaphor noun",
1005
- rule: "A noun borrowed from physics, chess or engineering to make a plain idea sound technical: substrate, wedge, vector, locus, vantage, nexus, primitive (as a noun), harness (as a metaphor), surface (as in API surface), bedrock, scaffolding (as a metaphor), modality, gold-plating, ratchet, evacuate (for moving code), endgame, north star, flywheel. Each one has a plainer concrete word. Substrate is base, wedge in is add, vector is way or method, gold-plating is more than the job needs, ratchet is the mechanism's real name or a limit that only tightens, evacuate is move out, endgame is the last phase. Pick the concrete word. These stay off the lint list because several are literal in a codebase: a language primitive and a test harness are the real names of real things.",
1006
- example:
1007
- '"The substrate the whole product sits on." / "Use pricing as a wedge into the account." / "Another vector for growth." / "That is the north star for the flywheel."',
1008
- },
1009
- {
1010
- id: "feeling-not-mechanism",
1011
- name: "Feeling instead of mechanism",
1012
- rule: 'A sentence that names how something feels instead of what it does: "the database stays close at hand", "SQL you can read", "types that follow your schema". The fix names the mechanism or a number. Ask what the sentence tells the reader to do or know and write that; if it cannot be restated as an instruction, a fact or a number, cut it. Second test: if the sentence could appear unchanged in another project\'s docs, it says nothing about this one.',
1013
- example:
1014
- '"The database stays close at hand." / "SQL you can actually read." / "Types that follow your schema." / "Built for teams that move fast."',
1015
- },
1016
- {
1017
- id: "applause-line",
1018
- name: "Applause line",
1019
- rule: 'A standalone sentence whose only job is to tell the reader the paragraph above it was impressive. It carries no new fact, no number and no instruction, and it is always short, so it reads as emphasis while adding nothing. The tell is that deleting it costs the passage nothing. Delete it, or replace it with the figure that would have earned the reaction. Not in `patterns` because "This is leverage." and "This is the schema." are the same shape and only one of them is empty.',
1020
- example:
1021
- '"This is leverage." / "This is a huge benefit." / "That\'s a lot of free growth!" / "There is no better marketing than that." / "But their loss is your gain!"',
1022
- },
1023
- {
1024
- id: "propped-adverb",
1025
- name: "Propped adverb",
1026
- rule: "An adverb holding up a verb that is too weak to stand alone. Runs quickly is is fast or the number, significantly improves is the measured delta. An adverb propping a verb means the verb is wrong, so replace the pair with one stronger verb or with the figure.",
1027
- example:
1028
- '"Significantly improves load time." / "Runs quickly on modest hardware." / "Dramatically reduces the number of steps."',
1029
- },
1030
- {
1031
- id: "long-sentence",
1032
- name: "Sentence past 30 words",
1033
- rule: "Ogilvy's third rule is short words, short sentences and short paragraphs, and the sentence half is the one that gets skipped. Past about 30 words the reader reaches the end holding none of the beginning, so they read it twice or they stop. The tell is a sentence with three or more clauses stacked by commas and `and`. Split it at the first `and` that starts a new idea. Not in `patterns` because a regex counting words across a hard-wrapped paragraph cannot tell a sentence from a bullet list; `course-lint.mjs` counts it where the text is structured.",
1034
- example:
1035
- '"It does the typing part of every lesson with you, one module a sitting, on your own site, and it stops at the end of each module because the reading stays yours." (32 words)',
1036
- },
1037
- {
1038
- id: "spelled-out-number",
1039
- name: "Spelled-out number",
1040
- rule: 'A quantity written as words instead of digits. A digit is the one shape in a line of prose the eye cannot skim, so every count, price, duration, percentage, date and measure ships as digits at any size: 15 clients, 3 hours a week, 20%, 60 seconds, $4,000, 2 of 5. Words are correct only where the number is not a quantity: one standing in for a or a single thing ("one page per space"), an idiom ("second nature", "at first hand"), and a number opening a sentence, which is better rewritten so it does not open one.',
1041
- example:
1042
- '"fifteen clients in and nothing is written down" / "three hours a week" / "a sixty second read" / "twenty per cent of the pipeline"',
1043
- },
1044
-
1045
- // --- 2026 corpus additions. Seven shapes named repeatedly across 31 videos on AI writing, read 6 Sep 2026. Evidence and counts: ai-doc/skills/content/writing/humanizer/references/detection.md.
1046
-
1047
- // All seven are density-judged, so none can move into `patterns`: one instance is style.
1048
- {
1049
- id: "semantic-incoherence",
1050
- name: "Semantic incoherence",
1051
- rule: "Words that co-occur in training data joined into a picture that cannot exist. The phrase scans on first read and collapses on second: nothing is overarching and undergirding at once, a slate is not filled the way a container is, an offensive is not nestled. Name the physical picture the sentence asks for and check that it exists. Diagnoses bad writing, never authorship: weak human writers mix metaphors constantly. See patterns.md 53.",
1052
- example:
1053
- '"Two overarching pillars undergird the approach." / "the offensive, nestled amid a year of war" / "silence like a thunderstorm folded into velvet"',
1054
- },
1055
- {
1056
- id: "figure-stacking",
1057
- name: "Figure stacking",
1058
- rule: "Three or more similes or metaphors laid end to end for one moment, instead of choosing the one that carries it. Each figure passes a line edit on its own; the pile is the tell. Same instinct at the word level produces adjective couplets where one adjective would do. Choose one and delete the rest. See patterns.md 54.",
1059
- example:
1060
- '"It bit like a thousand tiny teeth, a cruel lover, a quiet violence made beautiful." / "brittle and sharp" / "pastel and brittle"',
1061
- },
1062
- {
1063
- id: "base-adjective-recycling",
1064
- name: "Base adjective recycling",
1065
- rule: "The plainest adjectives (soft, quiet, sharp, light, warm, heavy, bright) returning every page, because the passage is not describing anything specific enough to need another word. The inverse of elegant variation. Mechanical check: search the draft for its five commonest adjectives and count. The repair is a specific detail, not a thesaurus. See patterns.md 55.",
1066
- example: '"The room was quiet. Her voice was quiet. A quiet dread settled."',
1067
- },
1068
- {
1069
- id: "emotional-flatlining",
1070
- name: "Emotional flatlining",
1071
- rule: "One heightened register held from the first line to the last, so nothing is emphatic because everything is. Structural rather than local, which is why it survives sentence-level editing. Read the loudest and the quietest passage: if they are the same volume, the draft has no shape. Fix it by taking pressure out of the ordinary passages, not by adding more to the big ones. Correct and expected in technical and reference text. See patterns.md 56.",
1072
- example:
1073
- '"A breakfast scene and a betrayal written at the same pitch." / A case study whose setup, turn and result all land equally hard.',
1074
- },
1075
- {
1076
- id: "asserted-transition",
1077
- name: "Asserted transition",
1078
- rule: "Moreover, Furthermore, In addition, However, On the other hand connecting two sentences whose relation is not the one the word claims. Two failures compound: the pile-up, and the assertion of a logic that is not there. Delete the connective and read the pair again; if the relation was real, the sentences still carry it. One however is not a tell. See patterns.md 57.",
1079
- example:
1080
- '"The region gets heavy rainfall. However, agriculture is a major industry." / "The city has 50,000 people. Moreover, it is near the coast."',
1081
- },
1082
- {
1083
- id: "unsupported-opening-claim",
1084
- name: "Unsupported opening claim",
1085
- rule: "An opening sentence placing the subject among the most significant shifts in history, or reshaping how people think, followed by a second sentence on a different subject. The diagnostic is the absence of a follow-up: the claim is made, no evidence is offered, and the next line moves on to another claim. Ask of the opening line: what in the rest of this makes that true? If nothing does, open on what is actually true. See patterns.md 58.",
1086
- example:
1087
- '"The rise of AI is one of the most profound transformations in human history, reshaping industries, societies and our understanding of intelligence."',
1088
- },
1089
- {
1090
- id: "compare-by-restating",
1091
- name: "Compare by restating",
1092
- rule: "Rather than contrasting, the sentence offers a second and third phrasing of what it just said. It reads as precision and adds nothing, and underneath it is a writer who does not trust the reader to have understood the first phrasing. The tell is that deleting every clause after the first costs no meaning. The subtle cousin of the negation pivot. See patterns.md 59.",
1093
- example:
1094
- '"Her lipstick is red, not just red but vivid, the kind of colour that demands attention." / "hoops, the kind that no one second-guesses"',
1095
- },
1096
- {
1097
- id: "named-feeling",
1098
- name: "Named feeling",
1099
- rule: 'The emotion labelled where its cause belongs. A reader told what to feel feels nothing, and the label is the cheapest sentence in the language to produce, which is why a model reaches for it first. Delete the word and write what caused it: "I was frustrated" is "the fourth build failed at 2am and I put the laptop in a drawer". The reader supplies the word. Never invent the cause to replace the label; go and get it. See patterns.md 63.',
1100
- example:
1101
- '"I was frustrated." / "It was exciting." / "I felt proud of what we built." / "It was a humbling experience."',
1102
- },
1103
- {
1104
- id: "clean-resolution",
1105
- name: "Clean resolution",
1106
- rule: "Every thread tied off, every lesson learned, the piece landing complete. Real work leaves loose ends, so a piece where everything resolves was built backwards from its conclusion and the reader feels the reverse-engineering. Leave the thing that is still broken in, and say plainly what you do not know yet. See patterns.md 64.",
1107
- example:
1108
- '"And that is when it all clicked." / "Looking back, I would not change a thing." / "The lesson here is simple."',
1109
- },
1110
- {
1111
- id: "smoothed-figure",
1112
- name: "Smoothed figure",
1113
- rule: 'A hedge in front of a round number, where the number is the evidence. Real measurement produces ugly figures, so "about 50%" and "roughly 3x" tell the reader you estimated or invented it. Write 47%, 2.8x, $9,340, 213 hours. If the real figure is not to hand, say you are estimating rather than smoothing it. A round number nobody is leaning on (5 clients, 10 minutes) is ordinary English, which is why this stays a human read. The vague-magnitude half is lint-enforced. See patterns.md 65.',
1114
- example: '"about 50% faster" / "roughly 3x the output" / "around $10k a month"',
1115
- },
1116
- {
1117
- id: "costless-claim",
1118
- name: "Costless claim",
1119
- rule: "Advice from somebody who risked nothing. Authority comes from having paid for the knowledge, so instruction with no price attached anywhere in the piece reads as compiled rather than lived. Name one real cost, money, hours, a relationship or a reputation, and one moment you were wrong, neither of them softened. A cost that did not happen is a fabrication, so where there is none, cut the claim rather than furnishing it. See patterns.md 66.",
1120
- example:
1121
- '"Always validate before you build." with no account of the thing the writer built and nobody wanted.',
1122
- },
1123
- ];
1124
-
1125
- /**
1126
- * The sentence shapes that CAN be matched exactly, so they are linted rather than left to a human read.
1127
- */
1128
-
1129
- /*
1130
- * WHY this list is separate from `shapes`: `shapes` is deliberately unlintable, because a regex for "negation pivot" would fire on every ordinary "is not".
1131
- */
1132
-
1133
- /*
1134
- * These are the sub-cases where the shape has a literal signature, and a signature is the only thing that turns a rule into a gate.
1135
- */
1136
-
1137
- /*
1138
- * The first two were caught in shipped slides on 24 Aug 2026, in a batch that had passed the word and phrase lists clean,
1139
- */
1140
-
1141
- /*
1142
- * which is what a rule with nothing behind it is worth.
1143
- */
1144
-
1145
- /*
1146
- * A pattern only belongs here if it can be wrong in one direction only. Anything that needs judgment stays in `shapes` and is enforced by the humanizer read.
1147
- */
1148
-
1149
- /*
1150
- * `id`, `name`, `test`, `rule` and `example` are required, and `example` is asserted against `test` by the suite, so a documented case its own regex cannot see fails the build.
1151
- */
1152
-
1153
- /*
1154
- * `view` is optional and names which reading of the draft the regex judges: the whole draft by default, or `faqless` for the one check an FAQ is allowed to fail.
1155
- */
1156
- // Grammar parts shared by `elided-passive` and `parallel-clauses`, kept as
1157
- // strings so each regex reads as the sentence shape it names.
1158
- const SUBJECT_STOP =
1159
- "(?!(?:I|We|You|They|He|She|It|This|That|These|Those|There|Here|Who|What|Whatever|Which|When|Where|Why|How|If|Once|Then|And|But|So|Or|Every|Each|Anything|Everything|Something|Nothing|Everyone|Anyone|Someone|Nobody|No|Not|Please)\\b)";
1160
- const PARTICIPLE =
1161
- "(?:[a-z]{3,}ed|(?:re|un|pre|over)?(?:built|made|kept|done|written|shown|sent|held|drawn|given|taken|chosen|driven|known|sold|told|paid|found|brought|bought|taught|grown|seen|spent|laid|hidden|tied))";
1162
- // Words that end a noun phrase: a determiner means verb plus object, an auxiliary means the verb is there.
1163
- const NOUN_PHRASE_STOP =
1164
- "(?!(?:the|a|an|your|our|their|its|my|his|her|this|that|it|them|me|us|you|anything|everything|something|nothing|is|are|was|were|be|been|being|has|have|had|can|will|would|should|may|might|must|do|does|did|get|gets|got|not|never|to)\\b)";
1165
- // Past tenses that take a preposition without being passive: "the team worked on".
1166
- const INTRANSITIVE_PAST =
1167
- "(?!(?:started|worked|moved|happened|stayed|waited|lived|failed|talked|looked|ended|lasted|belonged|listened|responded|reacted|agreed|arrived|returned|walked|travelled|traveled|asked|applied|voted|replied|opted|relied|depended|focused|pointed|referred)\\b)";
1168
- const PREPOSITION =
1169
- "(?:around|for|by|with|into|from|in|on|to|at|over|under|through|across|inside|onto|per|behind|beside|without|before|after|until|as)";
1170
- const FINITE_AUXILIARY =
1171
- "(?:is|are|was|were|has|have|had|can|will|would|should|must|may|might|does|do|did|gets|get)";
1172
- const CLAUSE_SUBJECT = `(?:(?:[Tt]he|[Yy]our|[Oo]ur|[Tt]heir|[Ee]ach|[Ee]very)[ \\t]+[a-z][\\w'’-]*|${SUBJECT_STOP}[A-Z][\\w&'’-]*)`;
1173
- const PRESENT_VERB =
1174
- "(?!(?:is|was|has|does|this|its|his|us|yes|plus|less|thus|across|always|perhaps|as|towards)\\b)[a-z]{2,}s";
1175
- const OBJECT_DETERMINER = "(?:the|a|an|your|its|their|our|his|her|every|each|all|it|them)";
1176
-
1177
- const PARTICIPLE_LIST =
1178
- "(?:[a-z]{3,}ed|built|made|kept|done|written|shown|sent|held|drawn|given|taken|chosen|driven|known|sold|told|paid|found|brought|bought|taught|grown|seen|spent|laid|hidden)";
1179
-
1180
- // A quantity, written either way. Thousands take a comma, because "3,556 videos"
1181
- // is how the measured claims in the video skills are written.
1182
- const COUNT =
1183
- "(?:\\d{1,3}(?:,\\d{3})+|\\d+|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)";
1184
- // Time units, for `bare-duration-clause`. Closed on purpose: every one of these
1185
- // is a noun in every reading, which is what makes a missing verb decidable.
1186
- const DURATION =
1187
- "(?:sec|secs|second|seconds|min|mins|minute|minutes|hour|hours|day|days|week|weeks|month|months|year|years)";
1188
- // A word that cannot carry a real second clause: no auxiliary, and no pronoun
1189
- // that would supply the subject ("15 minutes, it takes time" is a sentence).
1190
- const TAIL_WORD =
1191
- "(?!(?:is|are|was|were|be|been|being|has|have|had|can|will|would|should|may|might|must|does|do|did|gets|get|i|it|we|you|they|he|she|there|this|that)(?![\\w'’-]))[a-zà-ÿ][\\w'’-]*";
1192
- /**
1193
- * Where a sentence starts, for the patterns that judge a whole clause.
1194
- */
1195
-
1196
- /*
1197
- * A bare `\n` is deliberately not in it.
1198
- */
1199
-
1200
- /*
1201
- * Markdown prose here is hard-wrapped, so every line start looks sentence-initial and a clause anchored on `\n` reads the middle of a paragraph as its beginning:
1202
- */
1203
-
1204
- /*
1205
- * it put 4 false hits on shipped skills before the paragraph anchor replaced it, all of them mid-sentence ("the next video without the algorithm's help").
1206
- */
1207
-
1208
- /*
1209
- * A blank line is a real paragraph start, and `.!?:;` plus a space is a real sentence start.
1210
- */
1211
- const SENTENCE_OPEN = "(?:^|(?<=[.!?:;][\"'’”)\\]]?\\**[ \\t])|(?<=\\n\\n)|(?<=\\n\\n[ \\t]))";
1212
-
1213
- export const patterns = [
1214
- {
1215
- id: "seller-as-proof",
1216
- name: "The same agents we run our agency on",
1217
- test: /\bthe\s+same\s+(?:[\w-]+\s+){1,2}(?:that\s+)?(?:we|I)\s+(?:run|use|built|build)\b|\b(?:we|I)\s+run\s+(?:our|my|[A-Z][\w-]+)\s+(?:own\s+)?(?:[\w-]+\s+)?on\b|\b(?:our|my)\s+own\s+[\w-]+\s+(?:runs?|relies|is\s+built)\s+on\b|\bbuilt\s+(?:them|it)\s+for\s+(?:ourselves|us|[A-Z][\w-]+)\s+first\b|\bqui\s+font\s+tourner\s+notre\b|\bles\s+mêmes\s+(?:[\w'’-]+\s+){1,2}qui\s+font\s+tourner\b|\bconstruits?\s+d'abord\s+pour\b/i,
1218
- rule: 'Copy about the seller where the reader wanted their own result: "the agents we run our agency on" makes us the subject and the proof. Lead with what the client gets, in their numbers, and keep "we use it too" for a proof section, if anywhere. Ramzi, 30 Sep 2026, on his own agency\'s hero: "do not be focused about us, be focused on the client."',
1219
- example:
1220
- '"The same agents we run Acme on." / "The AI agents we run our agency on." / "the AI agents our own agency runs on" / "We built them for Acme first" / "Les mêmes agents qui font tourner Acme"',
1221
- },
1222
- {
1223
- id: "unasked-reassurance",
1224
- name: "The studio's own interface never changes",
1225
- test: /\b(?:its|our|the\s+[\w-]+'s|the\s+(?:tool|app|studio|page|site))\s+own\s+(?:interface|ui|chrome|look|design|styles?|colou?rs?)\s+(?:never|doesn't|does\s+not|won't|will\s+not|stays?|remains?)\b|\b(?:never|doesn't|does\s+not|won't|will\s+not)\s+(?:changes?|moves?|restyles?|touch(?:es)?|affects?)\s+(?:with|along\s+with)\s+(?:it|them|this|that|yours?)\b/i,
1226
- rule: 'A line spent on what does NOT happen, answering a worry the reader never had. It costs a sentence and plants the doubt it denies. Cut it, or say what the thing does. Ramzi, 28 Sep 2026, on the Editor OS brand page: "This is slop."',
1227
- example:
1228
- '"The palette your videos are drawn in. The studio\'s own interface never changes with it." / "It never changes with your brand"',
1229
- },
1230
- {
1231
- id: "the-one-x-everyone-y",
1232
- name: "The one map every agent reads",
1233
- test: /\bone\s+(?:[a-z./-]+\s+){1,2}(?:that\s+)?(?:every|each)\s+[a-z-]+\s+(?:reads?|uses?|needs?|looks?(?:\s+(?:at|up))?|checks?|knows?|shares?|sees?|opens?|follows?|runs?|works?\s+from|starts?\s+from)\b/i,
1234
- rule: 'The superlative-plus-universal line: "the one X every Y reads". It sounds like a definition and says nothing a reader can check, and it is the shape a diagram label takes when nobody stopped to say what the thing is. Say what it holds or what it does: "the file that lists your lists and statuses". Ramzi, 29 Sep 2026, on the ClickUp Agent Kit board: "the one xxx every xxx is AI slop."',
1235
- example:
1236
- '"the one map every agent reads" / "one file every tool reads" / "the one thing every founder needs"',
1237
- },
1238
- // The next 2 are Ramzi's, 23 Sep 2026, on course copy that passed this gate.
1239
- {
1240
- id: "object-as-agent",
1241
- name: "The page carries a fact",
1242
- test: /\b(?:page|row|file|task|field|lesson|card|list|slide|number|course|post|step|folder|doc|document|template|space|view|bucket|section)s?\s+(?:all\s+)?(?:carries|carry|holds|hold|owns|own|earns|earn|hands|gives|(?:lives|live|sits|sit)\s+(?:in|on|under|inside))\b|\bgive\s+(?:each|every|the|a)\s+(?:page|row|file|task|card|slide|post)\s+(?:one|a|1)\s+(?:fact|number|thing|claim|proof)\b/i,
1243
- rule: 'A thing doing what only a person does: a page carries, a number lives, a task sits, a row owns. It is a metaphor passed off as a statement, and it hides who acts. Say who does what, as a bare imperative: "Put one thing on each page that only you know", "Put every task in a BATCH bucket".',
1244
- example:
1245
- '"Every page carries one fact only you can supply" / "All the numbers live in 1 file" / "Open tasks all sit in a BATCH bucket" / "Give each page one fact only you can supply"',
1246
- },
1247
- {
1248
- id: "abstract-as-agent",
1249
- name: "This course gets ClickUp set up",
1250
- test: /\b(?:the|this|that|these|your|our|each|every|one|1)\s+(?:[a-z-]+\s+)?(?:course|lesson|module|prompt|guide|video|workshop|skill|playbook|framework|method|system|workspace|week|first|second|latter|former)s?\s+(?:(?:that|which)\s+)?(?:shows|teaches|walks|builds|reads|writes|plans|picks|finds|sets up|hands|helps|lets|runs|makes|turns|keeps|tells|does|handles|delivers|gets (?:you|your|it|them)|takes (?:you|them|your))\b/i,
1251
- rule: 'An abstract thing doing the reader\'s job: the course sets it up, the week runs, the prompt builds. The reader does the work, so make them the subject, as an order: "Set up your ClickUp with this course", "Use The Project Manager skill to plan your week in it". Ramzi, 23 Sep 2026.',
1252
- example:
1253
- '"This course gets your ClickUp set up" / "the week runs inside it" / "This lesson hands you 1 prompt"',
1254
- },
1255
- {
1256
- id: "place-as-person",
1257
- name: "See what the room is working on",
1258
- test: /\b(?:the|this|that|your|our|my)\s+(?:room|community|group|classroom|channel|space|school|newsletter|forum|list)\s+(?:is\s+|are\s+|was\s+|has\s+been\s+)?(?:working on|thinking|building|doing|talking about|discussing|saying|asking|wants|needs|shipping|learning|feels|believes|knows|decides)\b/i,
1259
- rule: 'A place doing a person\'s job: a room does not work, a community does not think. Name the people and what they did: "Read what members posted this week". Ramzi, 23 Sep 2026: "A room does not work. It\'s not a person."',
1260
- example: '"See what the room is working on" / "what the community is building"',
1261
- },
1262
- {
1263
- id: "thing-as-person",
1264
- name: "Automations that save you the afternoon",
1265
- // After "of a", the noun belongs to the one before it: "a review of an app complains" has the review complaining.
1266
- test: /(?<!\bof\s+(?:an?|the|this|that|its|their|your|our)\s+)\b(?:automations?|tools?|apps?|software|agents?|AI|bots?|dashboards?|systems?|process(?:es)?|templates?|workflows?|integrations?|boards?|scripts?|platforms?|CRMs?|inbox(?:es)?|calendars?|method|structure|views?)\s+(?:that\s+|which\s+|will\s+|can\s+|should\s+|finally\s+)?(?:saves?|gives?\s+(?:you|your|them|back)|frees\b|free\s+(?:you|up)|buys?\s+(?:you|back)|remembers?|notices?|decides?|thinks?|knows?|cares?|wants?|worr(?:y|ies)|forgets?|looks?\s+after|takes?\s+care\s+of|understands?|chases?|nags?|complains?|whines?|screams?|yells?|shouts?|begs?|sulks?|panics?|fears?|hates?|loves?)\b/i,
1267
- rule: 'A tool doing a person\'s job: an automation saves an afternoon, a dashboard knows, a system cares. It is a slogan, not a fact. Say what the tool does mechanically, or make the reader the subject: "Each one removes a decision somebody made by hand", "Get the afternoon back". Ramzi, 23 Sep 2026: "automations cannot save an afternoon. They are not a person."',
1268
- example: '"Automations that save you the afternoon" / "the dashboard knows who is late"',
1269
- },
1270
- {
1271
- id: "best-is-the-one",
1272
- name: "The best automation is the one that complains",
1273
- test: /\b[Tt]he\s+(?:best|worst|only|safest|cheapest|fastest|strongest|smartest|(?:most|least)\s+[a-z]+)\s+[a-z][\w'’-]*(?:\s+[\w'’-]+){0,5}?\s+(?:is|are|was)\s+the\s+ones?\s+(?:that|who|which|you|nobody|no\s+one)\b/,
1274
- rule: 'A superlative that crowns "the one that": the best automation is the one that complains, the best client is the one who leaves. It\'s a fortune cookie. The reader nods, then learns nothing they can check, and it often hides a tool acting like a person. Say the fact under it: "Set the automation to email you when a run fails, so a silent stop shows up the same day." Ramzi, 6 Oct 2026, on a LinkedIn draft graded A+: "using an automation as a human... it\'s an anti-pattern."',
1275
- example:
1276
- '"The best automation you own is the one that complains" / "The best client is the one who says no"',
1277
- },
1278
- {
1279
- id: "tool-does-the-job",
1280
- name: "13 skills do the writing",
1281
- test: /\b(?:skills?|prompts?|plugins?|tools?|agents?|templates?|files?|automations?|workflows?|models?|AI|bots?|courses?|lessons?|systems?)\s+(?:(?:that|which|will|can|then|now)\s+)?(?:do|does|did|handles?|takes?\s+care\s+of)\s+(?:all\s+)?(?:of\s+)?(?:the|your)\s+(?:heavy\s+lifting|hard\s+part|legwork|grunt\s+work|work|job|writing|reading|reads|thinking|research|selling|planning|editing|drafting|talking|analysis|rest)\b/i,
1282
- rule: 'A skill or a tool doing the person\'s work: skills do the writing, the agent does the research. It\'s an aphorism, and nobody learns what runs. Make the person the subject and name the tool as the thing they use: "Claude writes the page with the SEO skill", "You run the skill and it drafts the meta fields". Ramzi, 23 Sep 2026: "A skill does not do the writing, it\'s not a human."',
1283
- example:
1284
- '"13 public skills do the writing, the meta fields and the reads" / "the agent does the research"',
1285
- },
1286
- {
1287
- id: "free-as-figure",
1288
- name: "The moment capture is free",
1289
- test: /\bmoments?\s+(?:where\s+|when\s+)?(?:\w+\s+)?(?:is|are)\s+free\b|\b(?:capture|capturing|recording|context|clarity|feedback)\s+(?:is|are)\s+free\b|\bcosts?\s+nothing\s+to\s+(?:capture|record|write|ask|fix|say|check)\b|\bwhile\s+\w+ing\s+it\s+is\s+(?:still\s+)?free\b/i,
1290
- rule: 'A price put on something nobody pays for: a moment is free, capture costs nothing. It reads as an aphorism and says nothing the reader can act on. Say who does what, and when: "Capture each answer when it\'s first said, on the call or in the form". Ramzi, 23 Sep 2026.',
1291
- example:
1292
- '"The moment capture is free" / "One moment in every process costs nothing to capture"',
1293
- },
1294
- {
1295
- id: "ends-on-verb",
1296
- name: "A page the market asked for",
1297
- test: /\b(?!(?:\w*thing|during|morning|evening|ceiling|string|spring|wing|king|ring|bring|sing)\b)(?:[a-z]+(?:ed|ing)|paid|made|built|sold|bought|meant|said|sent|ask|asks|pay|pays|call|calls|look|looks|wait|waits|care|cares|account|accounts|search|searches|hope|hopes|vote|votes|apply|applies|reach|reaches|settle|settles|up)\s+(?:for|about|with|from)(?=\s*(?:[.!?;:,)"'”’\n]|$))|\b(?:it's|it is|is|was|are|were|been|being|gets|got|get)\s+(?:(?:first|1st|already|still|never|not|just|finally|actually|really|\w+ly)\s+)?(?:said|asked|written|made|sent|built|shipped|captured|heard|given|taken|seen|known|told|paid|read|shown|found|decided|agreed|signed|recorded|typed|spoken|answered|called|raised|mentioned|promised|approved|needed|wanted)(?=\s*(?:[.!?,;:)"'”’\n]|$))/i,
1298
- rule: 'A sentence that ends on its verb: "a page the market asked for", "when it\'s first said". The object is missing and the reader has to supply it. Name who does it and to what: "a page for a query that has impressions and no page", "when the client first says it". Ramzi, 23 Sep 2026.',
1299
- example:
1300
- '"Impressions with no page behind them is a page the market asked for" / "Capture the answer when it\'s first said"',
1301
- },
1302
- {
1303
- id: "count-of-total",
1304
- name: "62 of 99 agency owners",
1305
- test: /\b\d+\s+of\s+(?:the\s+)?\d{2,}\s+(?:[a-z-]+\s+)?(?:agenc(?:y|ies)|compan(?:y|ies)|founders?|owners?|clients?|orgs?|organi[sz]ations?|businesses|people|teams?|calls?)\b/i,
1306
- rule: 'A raw count out of a total reads like a spreadsheet and makes the reader do the division. Give the share, and who said it: "62% of the agency owners I\'ve met told me work goes missing". Ramzi, 23 Sep 2026: "This is way too specific. 62 of 99."',
1307
- example:
1308
- '"62 of 99 agency owners describe work going missing" / "73 of the 99 agencies I have worked with"',
1309
- },
1310
- {
1311
- id: "paired-backref",
1312
- name: "The first X, and the second Y in it",
1313
- test: /\bthe (?:first|former)\b[^.!?\n]{0,80}[,;.]\s+(?:and\s+)?the (?:second|other|latter)\b|, and\s+(?:the|your|a|an)\s+[^,.!?\n]{2,50}\b(?:inside|into|in|on|onto|under)\s+it\b/i,
1314
- rule: 'Two halves where the second only makes sense by pointing back at the first: "the first..., the second...", or ", and the week runs inside it". The reader has to hold the first half to parse the second, and it reads as an aphorism. Name each thing and give the reader the order: "Set up your ClickUp with this course. And use The Project Manager skill to plan your week in it." Ramzi, 23 Sep 2026.',
1315
- example:
1316
- '"The first builds the workspace, and the week runs inside it on the second." / "The first course sets it up. The second runs it."',
1317
- },
1318
- {
1319
- id: "you-injunctive",
1320
- name: "You put, you add",
1321
- test: /(?:^|(?<=[.!?:]\s)|(?<=\n))[ \t]*(?:[-*][ \t]+|\d+\.[ \t]+)?You (?:put|add|keep(?! \w+ing)|write|give|make|move|set|use|build|pick|name|delete|open|run|paste|end|create|turn|check|send|start|cut)\b/,
1322
- rule: 'An instruction dressed as a description of the reader: "You keep the numbers in 1 file". It reads as a model narrating the reader\'s day. Drop the "You" and give the order: "Keep the numbers in 1 file".',
1323
- example: '"You keep all the numbers in 1 file" / "You end each lesson with something built"',
1324
- },
1325
- {
1326
- id: "you-now-know",
1327
- name: "You now know",
1328
- test: /\bYou now know\b/,
1329
- rule: 'A recap that tells the reader what they learned before handing over the next thing. It opened 5 course finales in the same words. Cut it and start on the next thing: "Here\'s 1 prompt that runs the loop."',
1330
- example: '"You now know the loop and why each step is there."',
1331
- },
1332
- // The next 6 were read off the A20 Short on 23 Sep 2026, which passed the gate and was one tell per sentence. 0 hits on his own transcripts.
1333
- {
1334
- id: "stock-half-pivot",
1335
- name: "The easy half",
1336
- test: /\b(?:easy|easier|hard|harder|simple|tricky) half\b/i,
1337
- rule: 'A pivot off the shelf: "X is the easy half. The harder half is Y." It announces a turn instead of making one, and it repeats across scripts because a template taught it. Say what breaks: "It cuts the shouting. It keeps your rules."',
1338
- example: '"Deleting is the easy half." / "The counting is the easy half."',
1339
- },
1340
- {
1341
- id: "because-parallel",
1342
- name: "Same verb, because, twice",
1343
- test: /\b(\w+), because\b[^.!?]*[.!?]["'”’]?\s+[^.!?]*?\b\1, because\b/i,
1344
- rule: 'Two sentences in a row built on one frame, "X goes, because Y. Z goes, because W." A list pretending to be speech. Count the items out loud instead: "Number one: think step by step. Gone."',
1345
- example:
1346
- '"The old line goes, because it always thinks. The next one goes, because it already is."',
1347
- },
1348
- {
1349
- id: "called-splice",
1350
- name: "It's called X, and",
1351
- test: /, (?:it'?s|it is|this is|that'?s) called [^,.;]{1,60}, and\b/i,
1352
- rule: 'The name buried mid-sentence between 2 commas, then a second clause bolted on. Give the name its own sentence: "It\'s called prompt-audit."',
1353
- example: '"Anthropic shipped the fix, it\'s called prompt-audit, and it reads your files."',
1354
- },
1355
- {
1356
- id: "shipped-the-fix",
1357
- name: "Shipped the fix",
1358
- test: /\b(?:shipped|released|built|put out|dropped|rolled out) (?:the|a) fix\b/i,
1359
- rule: 'Launch-announcement voice. "The fix" presumes a problem the viewer never agreed to. Name the thing and show it running.',
1360
- example: '"Anthropic shipped the fix inside Claude Code."',
1361
- },
1362
- {
1363
- id: "never-meant",
1364
- name: "Places you never meant",
1365
- test: /\b(?:places|ways|things|spots) you never (?:meant|intended|expected|wanted)\b/i,
1366
- rule: "A vague consequence standing in for a real one. Name the place: which task, which output, what went wrong.",
1367
- example: '"A rule in capitals gets applied in places you never meant it to go."',
1368
- },
1369
- {
1370
- id: "made-sense-ago",
1371
- name: "Made sense a year ago",
1372
- test: /\bmade (?:perfect |total )?sense (?:back then|(?:a|one|two|three|\d+) (?:year|month|week)s? ago)\b/i,
1373
- rule: "A backstory with a date nobody measured. Either give the real date and source, or cut the history and state the current fact.",
1374
- example: '"All the MUSTs in there made sense a year ago."',
1375
- },
1376
- // The next 6 were read off Batch 2's clean reads the same day. At most 1 hit in 45,574 words of his own speech.
1377
- {
1378
- id: "and-escalation",
1379
- name: "And most of them are",
1380
- test: /, and (?:most|all|half|none|many) of (?:them|these|those) (?:are|were|have|go)\b|\b(?:there is|there's) and (?:it'?s|it is) the (?:weakest|worst|best|least|most)\b|, and everything else is\b/i,
1381
- rule: 'A claim, then a bigger claim bolted on with ", and most of them". The second clause inflates the first instead of adding a fact. Split it and give the second its own evidence, or cut it.',
1382
- example:
1383
- '"Every one of these tells turns up in good human writing, and most of them are centuries old." / "That\'s the most cited tell there is and it\'s the weakest one."',
1384
- },
1385
- {
1386
- id: "which-is-why",
1387
- name: "Which is exactly why",
1388
- test: /, which is (?:exactly |precisely )?(?:why|what|how)\b/i,
1389
- rule: "A tidy causal tail that closes the loop for the viewer. Say the cause as its own sentence, or let them reach it.",
1390
- example:
1391
- '"The service still making you money is the one keeping you stuck, which is exactly why you haven\'t touched it."',
1392
- },
1393
- {
1394
- id: "labelled-turn",
1395
- name: "The awkward part is that",
1396
- test: /\bthe (?:awkward|uncomfortable|hard|tricky|funny|scary|annoying|ugly|brutal|interesting|surprising|real) (?:part|bit|thing|truth)(?: here)? is that\b/i,
1397
- rule: "A label announcing that the next sentence matters. Delete the label and start on the fact.",
1398
- example:
1399
- '"The awkward part is that this list keeps rotting." / "The uncomfortable bit is that the branch you cut is still alive."',
1400
- },
1401
- {
1402
- id: "there-is-only",
1403
- name: "There's no X. There's only Y.",
1404
- test: /\bthere'?s no [^.!?]+[.!?]\s+there'?s only\b/i,
1405
- rule: "A negation pivot split over 2 sentences to sound final. State the Y.",
1406
- example: "\"There's no detector for this. There's only a list.\"",
1407
- },
1408
- {
1409
- id: "nobody-ever",
1410
- name: "Nobody has ever",
1411
- test: /\b(?:nobody|no one|no-one) (?:has |had )?ever\b/i,
1412
- rule: 'An absolute nobody measured. Say what you saw, with its count: "none of the 12 people I onboarded learned it from the doc."',
1413
- example: '"Nobody has ever learned a process from a paragraph."',
1414
- },
1415
- {
1416
- id: "is-where-people",
1417
- name: "Is where people stop",
1418
- test: /\bis where (?:people|you|most|everyone|teams?|clients?|readers?) (?:stop|quit|leave|give up|lose|drop)\b/i,
1419
- rule: 'A place standing in for a behaviour. Say what people do and when: "people stop reading after the first paragraph."',
1420
- example: '"A wall of paragraphs is where people stop reading."',
1421
- },
1422
- {
1423
- id: "every-opener",
1424
- // Case-sensitive so the lookahead spares Sitehub's plan names, which are proper nouns.
1425
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?(?:EVERY|[Ee]very|EACH|Each)\s(?!(?:Town|Search|Service|other|of)\b)/,
1426
- name: "Every or Each opener",
1427
- rule: 'A sentence that opens with Every or Each. It asserts a total in place of describing the thing, and swapping one for the other keeps the tell: Ramzi, 17 Sep 2026, on "Each workflow arrives named, grouped and explained": "each is also slop". Start the sentence on who does what: "We name, group and document your workflows."',
1428
- example:
1429
- '"Every number names its source article." / "Each workflow arrives named, grouped and explained."',
1430
- },
1431
- {
1432
- id: "participle-stack",
1433
- name: "Named, grouped and explained",
1434
- // 3 past participles in one list, tags allowed between. 0 hits on 190 of his posts, 3 on the website.
1435
- test: new RegExp(
1436
- `\\b${PARTICIPLE_LIST},\\s+(?:<[^>]+>\\s*)?${PARTICIPLE_LIST},?\\s+(?:and|or)\\s+${PARTICIPLE_LIST}\\b`,
1437
- ),
1438
- rule: 'Three past participles stacked as the result ("named, grouped and explained", "built, tested and documented"). Nobody does anything in it, and the list sounds thorough while saying nothing about how. Ramzi, 17 Sep 2026: "something that does not use passive words like named, grouped and explained." Give it a doer and active verbs: "We name, group and document your workflows."',
1439
- example:
1440
- '"Each workflow arrives named, grouped and explained." / "each one built, tested and documented"',
1441
- },
1442
- {
1443
- id: "participle-opener",
1444
- // Put, Cut, Set, Read and Run open imperatives as often as participles, so they're out.
1445
- // "Done when" names a step's finish line, the house shape since 4 Oct 2026.
1446
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?(?:(?!(?:Need|Seed|Speed|Feed|Bed|Red|Shed|Indeed|Breed|Weed|Deed|Greed|Embed|Proceed|Exceed|Succeed)\b)[A-Z][a-z]{2,}ed|Built|Made|Done(?!\s+when\b)|Kept|Written|Found|Taken|Shown|Grown|Known|Seen|Given|Chosen|Driven|Sold|Told|Held|Brought|Bought|Caught|Taught|Sent|Spent|Meant|Lost|Paid|Drawn|Worn|Named)\b,?\s+(?:in|for|by|with|to|from|on|around|into|once|before|after|at|off|out|up|over|under|through|across|and|like|as|when|while|where|the|your|our|their|a|an)\b/,
1447
- name: "Participle opener",
1448
- rule: "A sentence, heading or label that opens on a past participle (Built for, Found when, Measured once, Made to measure) with no subject. It is passive and nobody in it does anything. Say who does what: We built it for a phone. People find you when they search your town.",
1449
- example:
1450
- '"Built in your own colours" / "Found when your town searches" / "Named when somebody asks ChatGPT"',
1451
- },
1452
- {
1453
- id: "reader-benefit-tail",
1454
- // A conjunction or wh-word before `you` makes it a real clause (so your team can rest), not this.
1455
- test: /\b(?!(?:and|but|or|nor|so|yet|if|when|whenever|until|till|unless|because|before|after|once|now|then|here|there|where|what|whatever|how|why|who|whom|as|than|while|since|though|although|also|too|are|is|was|were|do|does|did|have|has|had|sure|think|suggest|guess|hope|bet)\b)[A-Za-z]{3,}\s+(?:(?:that|which)\s+)?(?:you|your\s+[a-z]+)(?:\s+(?:can(?:'t|’t|not)?|will|won't|won’t|could|would|should|actually)|['’]ll)\s+(?:(?:actually|really|finally|still|all)\s+)?[a-z]+[.!](?=["'’”<)\]]|\s|$)/i,
1456
- name: "Reader-benefit tail",
1457
- rule: "A sentence that ends on a noun plus a clipped relative clause about the reader: a capacity number your team can hold, a price your CFO will love, a system you can trust. The that is dropped and the verb's object is the noun before it, so the sentence closes on a bare modal verb that promises a feeling instead of stating a fact. Ramzi, 23 Sep 2026. Say what the thing does, with a number: a cap of 30 points per person a week.",
1458
- example:
1459
- '"and a capacity number your team can hold." / "A price your CFO will love." / "Systems that your team can actually maintain." / "A board you can trust."',
1460
- },
1461
- {
1462
- id: "comma-and-opener",
1463
- // Anchored to the start of the text, a sentence or a paragraph, and limited to ONE word before the comma, so a mid-sentence clause ("he said yes,
1464
-
1465
- // and then left") and a real adverbial pair ("On Monday, and only then, we ship") cannot reach it.
1466
-
1467
- // The word is letters only, so a date or a number opener does not match.
1468
-
1469
- // Not per line: a hard-wrapped Oxford list breaks before "integrators, and autonomous agents" and failed the CBAM about page, 15 Sep 2026.
1470
- test: /(?:^|(?<=[.!?]\s)|(?<=\n\n)|(?<=\n\n[ \t]))[ \t]*[A-Za-z]{2,12},\s+(?:and|but)\b/,
1471
- name: "Comma-and opener",
1472
- rule: "A sentence that spends its first word on a verdict, then hinges on a comma plus and or but before it says anything. The opener carries nothing the next clause does not, and the hinge is where a model hedges before answering. Ramzi, 14 Sep 2026, on a shipped Reddit comment. Delete the opener and start on the answer.",
1473
- example:
1474
- '"Yes, and the honest answer is that a full reconcile is not available." / "No, but the reason matters more than the number." / "Honestly, and this is the part nobody says, it never worked."',
1475
- },
1476
- {
1477
- id: "comma-and-title",
1478
- name: "The rest of the site, and what each part is for",
1479
- // A LINE with no sentence punctuation in it, hinged on a comma plus `and` and a wh-word.
1480
-
1481
- // The line shape is what makes it decidable: a heading, a card label or a copy-module value, never a comma mid-sentence in prose,
1482
-
1483
- // which ends on a stop and cannot reach the line anchor. The trailing `["'`]?[,;]?` is the source view, where a value ends on `",`.
1484
-
1485
- // The wh-word takes a space and a clause after it, so an Oxford list of bare wh-words ("What you do, where, and when") is a list and stays one.
1486
- test: /^[ \t]*(?:#{1,6}[ \t]+|[-*+][ \t]+|\*\*)?[A-Z][^.!?\n]{2,70},[ \t]+(?:and|or)[ \t]+(?:what|where|why|how|who|when|which|whether)[ \t][^.!?\n]{2,70}?["'`]?[,;]?[ \t]*$/m,
1487
- rule: 'A title that names a thing, then bolts a wh-clause on with a comma and `and`. The second half promises an explanation the page was going to give anyway, and the shape says the writer could not choose which half was the subject. Ramzi, 17 Sep 2026, on "The rest of the site, and what each part is for": the sloper should have caught it. Cut to the half that carries the page: "The rest of the site".',
1488
- example:
1489
- '"The rest of the site, and what each part is for" / "## Mail, and where every secret lives" / "The queue, and how a job gets claimed"',
1490
- },
1491
- {
1492
- id: "comma-hung-participle",
1493
- // The decidable half of `comma-hung-fragment`: a LINE that ends on a comma plus one participle.
1494
-
1495
- // Any `-ed` word, not a closed list: the list missed "resolved" and shipped it to the CBAM footer, 15 Sep 2026.
1496
-
1497
- // Per line, and the whole line is the fragment, so the shape is a headline, a card label or a slide band and never a comma mid-sentence in prose.
1498
-
1499
- // `[ \t]` and not `\s`, so a hard-wrapped paragraph cannot hand the anchor the next line.
1500
- test: /^[ \t]*(?:#{1,6}[ \t]+)?[A-Z0-9][^.!?\n]{2,60},[ \t]*(?:[a-zà-ÿ]{3,}ed|back|done|gone|built)[ \t]*[.!?]?[ \t]*$/m,
1501
- name: "Comma-hung participle",
1502
- rule: "A noun, a comma, and a past participle standing in for a sentence. Write the sentence: say who does it and what happens.",
1503
- example:
1504
- '"Sales tax report, filed" / "The week, planned" / "4 to 5 hours a week, back" / "EU carbon border data, resolved."',
1505
- },
1506
- {
1507
- id: "comma-hung-phrase",
1508
- // Per LINE, like `comma-hung-participle`: a label or headline whose second
1509
- // half is a stock verbless tail, or a mirrored "one X, one Y".
1510
- test: /^[ \t]*(?:#{1,6}[ \t]+|[-*+][ \t]+|[\w$]+:[ \t]*["'`])?(?:[A-Za-z][^.!?\n,]{1,50},[ \t]+(?:end to end|start to finish|top to bottom|front to back|beginning to end|step by step|in one place|at a glance|all in one)|(?:[Oo]ne|[Nn]o|[Ee]very|[Ee]ach)[ \t]+[\w'’-]+,[ \t]+(?:one|no|every|each)[ \t]+[\w'’-]+)[ \t]*[.!]?["'`]?[,;]?[ \t]*$/m,
1511
- name: "Comma-hung phrase",
1512
- rule: 'A name, a comma, then a stock tail with no verb ("end to end", "in one place"), or a mirrored "one X, one Y". It reads as a slogan and says nothing a sentence would not. Ramzi, 28 Sep 2026, on "Editor OS, end to end". Write the sentence, or cut to the name.',
1513
- example: '"Editor OS, end to end" / "one camera, one go" / "No setup, no code"',
1514
- },
1515
- {
1516
- id: "guided-tour-promise",
1517
- // A relative clause restating a thing's obvious job as hand-holding.
1518
-
1519
- // The verb set is closed and always takes "you" plus a direction word, so ordinary English does not reach it: "it takes you 3 minutes" has no direction word,
1520
-
1521
- // and "the wiki that covers one page per space" has no second person.
1522
- test: /\b(?:that|which)\s+(?:walks?|takes?|guides?|shows?)\s+you\s+(?:through|step by step|exactly)\b/i,
1523
- name: "Guided-tour promise",
1524
- rule: "A thing named, then a relative clause that restates its obvious job as hand-holding, usually with a totality claim bolted on. Say what the thing covers and let the reader work out that reading it helps.",
1525
- example:
1526
- '"A wiki that walks you through every piece." / "A guide that takes you step by step through everything you need." / "A dashboard that shows you exactly where you stand."',
1527
- },
1528
- {
1529
- id: "vague-attribution",
1530
- // An unnamed authority as the subject of a reporting verb.
1531
-
1532
- // A named source does not match, because the subject has to be the bare category word: "The Gartner report says 40%" and "Researchers and conservationists study the river" both read
1533
-
1534
- // clean.
1535
- test: /\b(?:experts?|observers?|analysts?|critics?|researchers?|industry reports?|studies|sources)\s+(?:say|says|argue|argues|believe|believes|note|notes|suggest|suggests|have cited|show|shows)\b/i,
1536
- name: "Vague attribution",
1537
- rule: "An unnamed authority standing in for evidence. Name the source or drop the claim.",
1538
- example:
1539
- '"Experts believe it plays a crucial role." / "Industry reports say the market doubled."',
1540
- },
1541
- {
1542
- id: "wasted-time-confession",
1543
- // Simple past plus a duration. The present perfect that the rule explicitly
1544
- // allows, "I have spent 10 years inside project tools", cannot match,
1545
- // because `spent` there is preceded by `have`.
1546
- test: /\bi\s+(?:spent|wasted|burned|lost)\s+(?:a|an|\d+|one|two|three|six)\s+(?:year|years|month|months|week|weeks|day|days)\b/i,
1547
- name: "Wasted-time confession",
1548
- rule: 'Simple past plus a duration plus the writer\'s own past foolishness, used as a credential or a closer: "I spent a year ...". The reader is asked to trade attention for a stranger\'s regret. Time served that built competence is a different sentence and is fine ("I have spent 10 years inside project tools"): present perfect, and the years bought something.',
1549
- example: '"I spent a year following up on people who were still inside their terms."',
1550
- },
1551
- {
1552
- id: "advisory-aside",
1553
- // The announcement, not the advice. Closed set of openers, each one a fixed phrase nobody writes by accident.
1554
-
1555
- // "one thing I'd/I'll/I would" added 14 Sep 2026, Ramzi: "this sentence is pure AI slop 'One thing I'd revisit'" — the same self-assigned-critique announcement as "one thing worth",
1556
-
1557
- // one pronoun over.
1558
- test: /\b(?:one thing worth|a quick note before|worth flagging|one last thing that|a small tip before|one thing (?:i'd|i'll|i would|i will))\b/i,
1559
- name: "Advisory aside",
1560
- rule: "The writer awarding themselves a bonus tip and announcing it before giving it. The announcement is pure throat-clearing and it grades the advice on the reader's behalf. State the thing.",
1561
- example:
1562
- '"One thing worth checking once: your own payment terms." / "Worth flagging: the Edge key expires."',
1563
- },
1564
- {
1565
- id: "stop-start",
1566
- name: "Stop this, start that",
1567
- // `stop`/`don't` and its answering `start`, across a stop, a comma, an `and`, or a line break. Bounded so it cannot reach across a paragraph and pair two unrelated sentences.
1568
-
1569
- // The past tense and the `and` joiner were added 24 Aug 2026, after "So I stopped putting lessons in the room and started putting playbooks in it" shipped into a
1570
-
1571
- // scheduled campaign and read clean here: `\bstop\b` does not match `stopped`, and the original required sentence punctuation between the halves. The narrative form is the same slogan wearing a story.
1572
- test: /\b(?:stop(?:ped)?|quit|don'?t|do not)\b[^.!?\n]{0,80}(?:[.!?,;\n]+|\s+and\s+)\s*(?:instead[, ]+)?(?:start(?:ed)?|begin|began)\b/i,
1573
- rule: "A negative imperative answered by its mirror, in either the imperative or the past tense. It is the negation pivot wearing a verb: the first half exists only to set up the swap, and the reader gets a slogan where an instruction or a fact was due. Write the instruction. The thing that stopped is implied by the thing that happens now.",
1574
- example:
1575
- '"stop adding tools. start taking them away." / "don\'t chase people, start building systems." / "I stopped shipping lessons and started shipping playbooks."',
1576
- },
1577
- {
1578
- id: "imperative-then-watch",
1579
- name: "Do this, watch that",
1580
- // Two imperatives back to back, the second one a spectator verb.
1581
-
1582
- // Bounded to one sentence each side so it cannot reach across a paragraph, and the second verb list stays short: "See the reference" is documentation.
1583
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n)(?:#{1,6}[ \t]+)?(?:Ask|Try|Take|Give|Tell|Show|Send|Pull|Type|Paste|Write|Read|Open|Run|Click|Drop|Post|Push|Put|Buy|Hire)\b[^.!?\n]{2,70}[.!?]\s+(?:Now\s+|Then\s+)?(?:[Ww]atch|[Nn]otice|[Oo]bserve)\b[^.!?\n]{2,70}[.!?]/,
1584
- rule: "An order to the reader followed by an order to admire the result. The second sentence states no fact: it tells the reader what to feel about the first, and the pair reads as a trailer for the thing instead of the thing. Write what happens, in one sentence, with a subject.",
1585
- example:
1586
- '"Ask a model for one line. Watch what it pays out instead." / "Run the import. Watch the duplicates disappear."',
1587
- },
1588
- {
1589
- id: "numeric-anaphora",
1590
- name: "Number, number, number",
1591
- // Two or more number-led noun phrases in a row, comma separated.
1592
-
1593
- // Bounded to three words a phrase so it cannot reach across a clause and pair two unrelated counts, and to 3 digits a number,
1594
-
1595
- // because "15 rue des Halles, 75001 Paris" is a postal address and failed 3 legal pages on the CBAM site, 15 Sep 2026.
1596
- test: /\b(?:one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|\d{1,3})\s+(?:[a-z][a-z-]{2,}\s+){0,2}[a-z][a-z-]{2,},\s+(?:and\s+)?(?:one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|\d{1,3})\s+(?:[a-z][a-z-]{2,}\s+){0,2}[a-z][a-z-]{2,}\b/i,
1597
- rule: "A run of counted noun phrases standing in for a sentence. The numbers make it feel measured while the line states nothing, and the cadence is doing the work a verb should. Write the sentence, or set the counts as a list where the reader can actually scan them.",
1598
- example:
1599
- '"one form, five fields, and the routing behind it." / "three jobs, four questions, twelve answers."',
1600
- },
1601
- {
1602
- id: "faux-insight-setup",
1603
- name: "What nobody tells you",
1604
- // A setup noun ("what", "the part", "the math") handed to an ignorant crowd and a verb of telling.
1605
-
1606
- // One-directional: an ordinary "nobody tells me what to do" has no setup noun in front of it and does not match.
1607
-
1608
- // `skips` is deliberately absent, because "the pass everyone skips" is a real course term rather than a flourish.
1609
- test: /\b(?:what|the\s+[a-zà-ÿ]+)\s+(?:nobody|no one|hardly anyone|most people|everyone|everybody)\s+(?:tells|warns|shows|mentions|misses|runs|talks about|leaves out|gets wrong)\b/i,
1610
- rule: "A setup clause that casts the writer as the one person who sees it, then delivers an ordinary claim. It needs an implied crowd to be wrong, and it opens on the writer's vantage rather than on the reader's problem. Cut the setup and let the claim carry itself; if the claim cannot stand without the crowd, it was not worth the sentence.",
1611
- example:
1612
- '"Here is what nobody tells you before you upgrade." / "Here is the math nobody runs." / "The part everyone misses: distribution is the moat."',
1613
- },
1614
- {
1615
- id: "removal-closer",
1616
- name: "That is the part we took out",
1617
- // The decidable half of the `deadpan-closer` shape: a demonstrative, a setup noun and a past-tense removal verb.
1618
-
1619
- // Ramzi, 11 Sep 2026, on this exact line shipping to the Sitesmiths page: "that is the part we is AI slop".
1620
- test: /\bthat(?:'s|\s+is)\s+the\s+(?:part|bit|piece|step|thing)\s+(?:we|i|they)\s+(?:took|cut|removed|dropped|deleted|killed|skipped)\b/i,
1621
- rule: 'A flat demonstrative parked after a list, pointing back at it instead of stating the new thing. The reader has to hold the list in their head to decode `that`, and the sentence adds no fact. Name what you do: "So we build yours before we ask you for anything."',
1622
- example:
1623
- '"That is the part we took out." / "That\'s the bit we cut." / "That is the step we removed."',
1624
- },
1625
- {
1626
- id: "where-it-came-from",
1627
- name: "Where the X came from",
1628
- // Heading and topic-sentence shape. `Where` plus a subject plus `came from`
1629
- // or `comes from`, inside one clause.
1630
- test: /\bwhere\s+[^.!?\n]{2,60}\b(?:came|comes|come)\s+from\b/i,
1631
- rule: 'A heading that promises an origin story and then delivers the fact plainly anyway. It buys a beat of suspense the reader did not ask for. Name the fact: "the 104 hours" rather than "where the 104 hours came from".',
1632
- example: '"Where the 104 hours came from" / "Where the gap comes from"',
1633
- },
1634
- {
1635
- id: "hollow-actually",
1636
- name: "That actually",
1637
- // `actually` inside a relative clause, or standing in a heading. Both are pure intensifier: the word is doing the work the noun should.
1638
-
1639
- // Bare `actually` elsewhere can be load-bearing (a measured result against a predicted one), so it is deliberately not matched.
1640
- test: /\b(?:that|who|which|people|nobody|somebody)\s+actually\b|^#{1,6}\s+[^\n]*\bactually\b/im,
1641
- rule: "`actually` in a relative clause is the writer insisting rather than the noun earning it. Traffic that actually sells is just traffic that sells, and if the contrast matters, name the thing it beats. In a heading it is always filler.",
1642
- example: '"get traffic that actually sells" / "a thumbnail people actually click"',
1643
- },
1644
- {
1645
- id: "spelled-out-quantity",
1646
- name: "Spelled-out quantity",
1647
- // The lintable half of the `spelled-out-number` shape. A cardinal word followed by the thing it counts is always a quantity, so it always wants digits.
1648
-
1649
- // `one` is left out because it doubles as an article, and a bare cardinal with no noun after it ("two of the three") is left out because the shape entry
1650
-
1651
- // still covers it for the human read.
1652
-
1653
- // The lookbehind added 31 Aug 2026: `hundred|thousand|million` are on the list for "three thousand euros", and without it they also fired on a figure that is already correct,
1654
-
1655
- // so "17 million last year" failed the gate it passes by construction. Caught auditing the 45 planned posts.
1656
-
1657
- // The `Sigma` exclusion added 6 Sep 2026: Six Sigma is the name of a methodology, so the number is not counting anything and no digit belongs there.
1658
-
1659
- // It fired 8 times across the UpSys blog, in both languages.
1660
-
1661
- // `Factor` joined it 7 Sep 2026 for the same reason: Two-Factor Authentication is a feature name, and a screenshot's alt text has to quote the label the screenshot shows.
1662
-
1663
- // `way` joined 9 Sep 2026: two-way sync is a feature name on the Airtable to Sheets pricing page and in the add-on UI.
1664
-
1665
- // The singular is always an adjective, and `\b` keeps "two ways" caught, which is a real quantity.
1666
-
1667
- // A relative pronoun or `of` after the cardinal means it counts no noun ("the one or two that carry weight"), 15 Oct 2026.
1668
- test: /(?<!\d[\s-])\b(?:two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|hundred|thousand|million)[\s-]+(?!(?:Sigma|Factor|way|that|which|who|whom|whose|of)\b)[a-z]{3,}/i,
1669
- rule: "A quantity written as words. A digit is the one shape in a line of prose the eye cannot skim, so every count, duration, price and measure ships as digits: 40 pages, 19 minutes, 3 channels, 20%. See the `spelled-out-number` shape for the exceptions.",
1670
- example:
1671
- '"forty pages" / "nineteen minutes beat twenty-nine" / "twenty per cent of the pipeline"',
1672
- },
1673
- {
1674
- id: "spelled-out-label",
1675
- name: "Numbered label in words",
1676
- // The other half of `spelled-out-quantity`, which cannot see this one: a label is followed by a colon or a heading break rather than by the noun it counts,
1677
-
1678
- // so "Lesson two:" never reaches that test. The noun list is closed and every entry is an index into a set the writer made.
1679
-
1680
- // `day` is deliberately absent, because "from day one" is an idiom rather than a count, and `point` is absent because "point five" is a decimal.
1681
- test: /\b(?:lesson|step|part|phase|chapter|module|rule|tip|slide|stage|round|week|version|level)\s+(?:one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)\b/i,
1682
- rule: "A label that counts, written as a word. It is the same rule as any other quantity: a digit is the one shape in a line the eye cannot skim, and a label is read at a glance more than any other line on the page. Write Lesson 3, Step 2, Part 4.",
1683
- example: '"Lesson one: stop selling the tool" / "Step three" / "Part two of the build"',
1684
- },
1685
- {
1686
- id: "ring-label",
1687
- name: "Ring as a numbered label",
1688
- // Ramzi, 19 Sep 2026, on a board that labelled its four cards RING 1 to RING 4: the ring is the drawing, not the thing.
1689
-
1690
- // A number is allowed to follow the real noun (Load 2, Step 3), never the shape it was drawn as.
1691
-
1692
- // Restricted to a following number so "ring the bell" and a phone ringing stay ordinary English.
1693
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n)\s*(?:#{1,6}[ \t]+)?(?:[-*•]\s*)?ring\s+(?:\d+|one|two|three|four|five|six|seven|eight|nine|ten)\b/i,
1694
- rule: "A label naming the picture instead of the thing. The reader has to hold your diagram in their head before the line means anything, and the real noun was available. Write Load 2, Step 3, the schedule.",
1695
- example: '"RING 2" / "Ring one: your business" / "Ring 4, the schedule"',
1696
- },
1697
- {
1698
- id: "comma-run",
1699
- name: "Comma-run list",
1700
- // 3+ fragments strung on commas with no conjunction anywhere, all short.
1701
-
1702
- // Ramzi, 19 Sep 2026, on "One connector, read the permission screen, 12 slides back": *"For AI, the sequence of commas is AI slop."* A written list has "and" in it,
1703
-
1704
- // or it is 2 items, or it is bullets.
1705
- view: "prose",
1706
- test: /(?:^|[.!?:\n]\s*)(?![^.!?\n]*(?:\b(?:and|or|but|nor|then|so|plus|et|ou|mais|ni|puis|donc)\b|=>))[^.!?\n,]{4,40},\s[^.!?\n,]{4,40},\s[^.!?\n,]{4,40}(?=[.!?\n]|$)/i,
1707
- rule: "Three or more fragments hung on commas with no conjunction. It reads as a machine emptying a list rather than a person making a point: nothing in it is subordinate to anything else, so the reader has no idea which part matters. Use two items and a conjunction, or write bullets.",
1708
- example:
1709
- '"One connector, read the permission screen, 12 slides back." / "Fast, cheap, reliable." / "The brief, the offer, the tone."',
1710
- },
1711
- {
1712
- id: "nobody-opener",
1713
- name: "Nobody opener",
1714
- // Sentence-initial only. Mid-sentence "and nobody reads it" is an ordinary
1715
- // clause; the tell is the crowd taking the first position, where the
1716
- // reader's own problem belongs.
1717
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n)\s*(?:#{1,6}[ \t]+)?(?:nobody|no one|no-one)\s+[a-zà-ÿ]/i,
1718
- rule: "A sentence opening on what an unnamed crowd does not do. It spends the strongest position in the line on an absence nobody can check, and the claim after it needs the crowd to be wrong before it means anything. Write what the reader in front of you wants.",
1719
- example:
1720
- '"Nobody wakes up wanting an app." / "No one reads the second page." / "Nobody has time for this."',
1721
- },
1722
- {
1723
- id: "reassurance-relative",
1724
- name: "Reassurance relative clause",
1725
- // The verb set is deliberately short: comprehension and ease only.
1726
-
1727
- // "a form you can fill in on your phone" carries a fact about the form and passes; "a report you can read" carries only the promise that it is not
1728
-
1729
- // bad.
1730
- test: /\b(?:a|an|the)\s+(?:[a-zà-ÿ-]+\s+){0,3}[a-zà-ÿ-]+\s+(?:you\s+can\s+(?:actually\s+)?(?:read|use|understand|trust|follow|act\s+on)|that\s+(?:actually|just)\s+works|that\s+makes\s+sense)\b/i,
1731
- rule: "A noun, then a relative clause whose only content is that the noun is not bad. It defends the thing against a complaint the reader never made, and it concedes that the usual version of the thing is unreadable. Say what is in it: 4 numbers, one page, the 3 jobs it lists.",
1732
- example:
1733
- '"A monthly report you can read" / "a dashboard you can actually use" / "a process that makes sense" / "a tool that just works"',
1734
- },
1735
- {
1736
- id: "indefinite-stand-in",
1737
- name: "Indefinite stand-in",
1738
- // Bounded to the temporal and existential frames, where the indefinite is standing in for a named thing.
1739
-
1740
- // An ordinary "anything else you need" is a real quantifier over a real set and passes.
1741
- test: /\b(?:before|until|when|while)\s+(?:anything|nothing|anyone|no\s?one|nobody|something|someone)\s+(?:exists|existed|is\s+(?:built|written|made|there|real)|happens|happened|has\s+happened)\b/i,
1742
- rule: "An indefinite pronoun standing where the thing belongs. It sounds absolute and costs no research, and the reader cannot picture it. Name what does not exist yet: the site, the quote, the first invoice.",
1743
- example:
1744
- '"A quote to sign before anything exists." / "You commit before anything is built." / "They bill you when nothing has happened."',
1745
- },
1746
- {
1747
- id: "recap-opener",
1748
- name: "Recap opener",
1749
- // Bounded to recap verbs, because "Now that you have a big enough audience" is a real condition Ramzi says out loud.
1750
-
1751
- // From Vercel's writing guidelines, 13 Oct 2026; its two hits in our corpus were both other people's YouTube scripts.
1752
- test: /(?:^|[.!?]["”]?\s+)(?:Now that (?:we|you)(?:'ve|’ve| have)? (?:covered|seen|explored|learned|understand|know|set up|looked at|gone through|walked through|built)|With (?:this|that|these|everything|all (?:of )?(?:this|that))\b[^.,]{0,30}\b(?:in place|complete|done|set up|out of the way|covered|sorted|settled)|Having (?:covered|set up|explored|looked at|seen|established|walked through)|(?:So far|Up to now|By now),? (?:we|you)(?:'ve|’ve| have))\b/i,
1753
- rule: "A sentence that opens by summing up what the reader just read. They were there. Start on the next point.",
1754
- example:
1755
- '"Now that you understand the mechanics, the next question is which platform." / "With this setup complete, deploy the worker." / "Having covered the basics, we move to pricing." / "So far we\'ve built the form."',
1756
- },
1757
- {
1758
- id: "named-feeling",
1759
- name: "Named feeling",
1760
- // The label form only, where the copula does all the work. A feeling verb acting on something ("it frustrates the client every Friday") carries a fact and passes.
1761
-
1762
- // Zero hits across his 60,000 words, counted 10 Sep 2026.
1763
- test: /\b(?:i\s+(?:was|am|felt|feel)\s+|it\s+(?:was|is)\s+(?:a\s+|an\s+)?)(?:truly\s+|really\s+|genuinely\s+)?(?:frustrated|frustrating|exciting|excited|thrilled|thrilling|humbling|humbled|proud|amazed|amazing|grateful|overwhelmed|overwhelming|inspiring|inspired|rewarding|incredible|surreal)\b/i,
1764
- rule: "The emotion named where its cause belongs. Delete the label and write the thing that caused it, and the reader supplies the word themselves. Never invent a cause to fill the gap: go and get the real one, or cut the sentence.",
1765
- example: '"I was frustrated." / "It was exciting." / "It was a humbling experience."',
1766
- },
1767
- {
1768
- id: "clean-resolution",
1769
- name: "Clean resolution",
1770
- // The closing formulas only. The diagnosis behind them, a piece with no
1771
- // loose ends left, is `clean-resolution` in `shapes` and needs a read.
1772
- test: /\b(?:that(?:(?:'|’)?s| is| was) when it (?:all )?clicked|looking back,? i (?:would ?n(?:'|’)?t|would not) change|the lesson here is|that(?:(?:'|’)?s| is) the (?:real )?lesson|i\s+could ?n(?:'|’)?t believe what i was)\b/i,
1773
- rule: "A closing formula that ties every thread off and states the takeaway. It is the sound of a piece built backwards from its conclusion. End on what is still open, or on the fact, and let the reader draw the lesson.",
1774
- example:
1775
- '"And that is when it all clicked." / "Looking back, I would not change a thing." / "The lesson here is simple."',
1776
- },
1777
- {
1778
- id: "vague-magnitude",
1779
- name: "Vague magnitude",
1780
- // A magnitude word standing in for a count. Zero hits across his 60,000 words, counted 10 Sep 2026, so the shape is nobody's ordinary English here.
1781
-
1782
- // `hundreds of thousands of X` is excluded: it modifies a real scale.
1783
- test: /\bcountless\s+[a-z]|(?<!\bof\s)\b(?:hundreds|thousands|millions|dozens|scores)\s+of\s+(?!thousands\b|millions\b)[a-z]/i,
1784
- rule: "A magnitude word where a count belongs. It sounds measured and proves nothing, and it costs the writer no research. Write the figure, ugly as it is: 213 hours, 47 clients. If there is no figure, drop the claim.",
1785
- example:
1786
- '"hundreds of hours saved" / "thousands of dollars a month" / "countless integrations"',
1787
- },
1788
- {
1789
- id: "comma-not-pivot",
1790
- name: "Comma pivot",
1791
- // The `negation-pivot` shape was review-only because "is not" is ordinary English.
1792
-
1793
- // The comma form is not: a clause, a comma, then `not` plus a determiner is the swap every time, so it is decidable and it fails.
1794
- test: /,\s+(?:and\s+|but\s+)?not\s+(?:a|an|the|just|only|your|our|my|its|his|her|their|this|that)(?![\p{L}\p{N}_])/iu,
1795
- rule: "A line that lands on what the thing is not. The half after the comma exists to make the half before it sound earned, and the reader is handed a contrast where an instruction was due. Write the instruction alone: what it is not is implied by what it is.",
1796
- example:
1797
- '"Open on the state they want, not the app." / "Sell the change, not the tool." / "Write the mechanism, not the slogan."',
1798
- },
1799
- {
1800
- id: "comma-not-pivot-fr",
1801
- name: "Comma pivot (FR)",
1802
- test: /,\s+(?:et\s+)?pas\s+(?:(?:un|une|le|la|les|de|votre|vos|ton|ta|tes|son|sa|ses)(?![\p{L}\p{N}_])|[ld]['’])/iu,
1803
- rule: "La version française du pivot: une virgule, puis ce que la chose n'est pas. Écrire l'instruction seule.",
1804
- example: '"Vendez le changement, pas l\'outil."',
1805
- },
1806
- {
1807
- id: "singular-count-flourish",
1808
- name: "The one X in this Y",
1809
- // `the one <noun>`, a preposition, then a deictic `this` or `that`, which is always the writer pointing at their own artefact.
1810
-
1811
- // Bounded to one noun on each side so it cannot reach across a clause.
1812
-
1813
- // `the` is deliberately not accepted in the second slot: "the one file in the folder" is a fact about the world and stays legal,
1814
-
1815
- // while "in this" and "in that" only ever grade the thing the writer just made.
1816
- test: /\bthe one\s+[a-zà-ÿ][a-zà-ÿ-]+\s+(?:in|of|on|inside|behind|about)\s+(?:this|that)\s+(?:whole\s+|entire\s+|single\s+)?[a-zà-ÿ][a-zà-ÿ-]+/i,
1817
- rule: "A count used as a promotion. It tells the reader that what follows is the only one of its kind, which is the writer grading their own work, and the count is never checkable. It fits any noun, so it spreads: 6 courses closed on the same heading and 5 more files carried the same figure. Name the thing plainly and let it be the only one.",
1818
- example:
1819
- '"The one ask in this Classroom" / "the one rule in this whole system" / "the one thing on this panel that must keep its height"',
1820
- },
1821
- {
1822
- id: "echoed-word",
1823
- name: "Echoed word",
1824
- // The last word of one sentence opening the next, article allowed.
1825
-
1826
- // The echo is the whole tell, so no negation is required: `nobody drops the ball. the ball has nowhere to sit.` is the same figure as `you are the glue.
1827
-
1828
- // glue does not scale.`
1829
- test: /\b([a-zà-ÿ]{3,})\s*[.!?]["'’”)\]]?[\s\n]+(?:the |a |an |it |that )?\1\b/i,
1830
- rule: "The last word of a sentence handed straight to the next one as its subject. It reads as a written figure rather than as speech, and the second sentence almost always spends itself restating the first. Say the second thing without picking the word back up, or cut one of the two.",
1831
- example:
1832
- '"you are the glue. glue does not scale." / "nobody drops the ball. the ball has nowhere to sit."',
1833
- },
1834
-
1835
- {
1836
- id: "appositive-heading",
1837
- name: "The X, participled",
1838
- // Anti-voice 13, the half that is decidable.
1839
-
1840
- // The shape is a determiner-led noun phrase, a comma, and a participle or a relative pronoun, with the whole thing being a heading: no main verb ever arrives.
1841
-
1842
- // The determiner is the entire tell, and it is what a first attempt on 6 Sep 2026 missed: bare `<noun phrase>, <participle>` matched 25 lines across the UpSys corpus and
1843
-
1844
- // almost all were legitimate feature labels ("Your tools, connected", "Automations, switched on", "Price per user, per month, billed yearly").
1845
-
1846
- // A label drops the article; a comment on a thing already named keeps it.
1847
-
1848
- // Re-measured with the article required: 6 of 6 known instances of the shape, 0 false hits on 24,366 copy units.
1849
-
1850
- // Noun phrase widened to 8 words, 8 Sep 2026: at 4 it missed the shipped slide "The same 5 containers for every client, nested 3 deep".
1851
-
1852
- // Anchored to a quote, a backtick or a markdown heading on the left and to a quote or a line end on the right,
1853
-
1854
- // so it only fires on a whole string.
1855
-
1856
- // That is what keeps an ordinary mid-sentence appositive out ("The report, published in 2024, showed a 40% gap"): the sentence runs on past a full stop the character class refuses.
1857
-
1858
- // The line end refuses a lowercase continuation, added 6 Sep 2026 after a hard-wrapped source string ("...that doc moves run\n\t\t\t\ton.") read as a heading.
1859
-
1860
- // A wrapped sentence resumes in lowercase; a heading's body does not. English only.
1861
-
1862
- // French uses the definite article for a generic plural, so "Les automatisations, activées" is the legitimate label "Automations, switched on" and the tell does not survive translation.
1863
- test: /(?:^|["'`]|#{1,6}[ \t])[ \t]*(?:the|a|an)\s+(?:[\w-]+\s+){0,7}[\w-]+,\s+(?:[a-z]+(?:ed|ing)|(?:re|un|over|pre)?(?:built|run|made|done|kept|held|sold|told|given|taken|written|drawn|shown|set|put|sent|spent|left|lost|found|chosen|driven|known|paid|read|met|won|cut|bought|brought|caught|taught|thought)|which|who|that|where|when)\b[^.!?\n"'`<>]{0,70}(?=[ \t]*(?:["'`]|$(?![\r\n][ \t]*[a-z])))/im,
1864
- rule: "A heading built as a thing, a comma and a comment on that thing, with no verb anywhere. It reads as a caption rather than as a claim, and the half after the comma grades the half before it instead of saying what happens. Write the sentence: name the subject and give it a verb.",
1865
- example:
1866
- '"The architecture, decided before it is built" / "The build, run against your real delivery" / "The adoption, which is the part that fails"',
1867
- },
1868
-
1869
- {
1870
- id: "appositive-as-clause",
1871
- name: "The X, as we found it",
1872
- // `appositive-fragment`'s `as` half: noun phrase, comma, `as`, pronoun, verb, no main verb
1873
- // ("The cut, as it stands"). 17 Sep 2026: 11 hits in 30,898 files, 0 false.
1874
- test: /(?:^|["'`]|#{1,6}[ \t])[ \t]*(?:the|a|an|your|our|their|his|her|its|my)\s+(?:[\w-]+\s+){0,7}[\w-]+,\s+as\s+(?:we|you|they|it|i|he|she)\s+[\w-]+[^.!?\n"'`<>]{0,70}(?=[ \t]*(?:["'`]|$(?![\r\n][ \t]*[a-z])))/im,
1875
- rule: "A thing, a comma, and an `as` clause that only says when it was seen. No main verb arrives, so it reads as a museum caption rather than a claim, and on a page written to somebody it also drops them into the third person. Write the sentence: say who did what.",
1876
- example:
1877
- '"Your website, as we found it" / "The cut, as it stands" / "The entitlement, as it now stands"',
1878
- },
1879
-
1880
- // --- blader/humanizer 3.0.0 catch-up, 21 Sep 2026. Four shapes its rebuilt
1881
- // list names that no phrase can hold. ---
1882
- {
1883
- id: "deep-saying",
1884
- test: /\b(?:is|are)\s+the\s+(?:language|currency|architecture|grammar|oxygen)\s+of\b|\bbecomes\s+a\s+trap\b/i,
1885
- name: "Saying that sounds deep",
1886
- rule: "An ordinary point dressed as a hidden truth. Replace the aphorism with the specific claim it stands in for.",
1887
- example:
1888
- '"Symmetry is the language of trust." / "Efficiency becomes a trap when teams forget the human layer."',
1889
- },
1890
- {
1891
- id: "clipped-negative-tail",
1892
- test: /,\s+no\s+(?:guessing|guesswork|fluff|fuss|surprises|hassle|jargon|ceremony|bloat|nonsense|hype|gimmicks)\b/i,
1893
- name: "Clipped negative tail",
1894
- rule: "A comma and a `no X` that denies something nobody claimed, so the sentence sounds larger. State what the thing does.",
1895
- example:
1896
- '"The options come from the selected item, no guessing." / "Setup takes ten minutes, no fluff."',
1897
- },
1898
- {
1899
- id: "dotted-emphasis",
1900
- test: /\b(?:every|each)\.\s+(?:single|one)\b/i,
1901
- name: "Periods between the words",
1902
- rule: "Emphasis by full stop after every word. Write the sentence and let the fact carry the weight.",
1903
- example: '"Every. single. day." / "Each. one. matters."',
1904
- },
1905
- {
1906
- id: "previous-version-narration",
1907
- test: /\b(?:was|were)\s+(?:added|introduced|created)\s+to\s+replace\b|\breplaces?\s+the\s+(?:previous|old|former|earlier|original)\s+(?:approach|version|implementation|behaviou?r|way)\b/i,
1908
- name: "Writing about the previous version",
1909
- rule: "Docs and comments describe what the text replaced instead of the current behavior. Say what it does now; the history lives in the changelog and git.",
1910
- example:
1911
- '"This function was added to replace the previous approach of iterating all items." / "It replaces the old implementation."',
1912
- },
1913
-
1914
- // --- Wikipedia:Signs of AI writing, read 2026-09-05 --- The signs from that page whose signature is literal enough to lint.
1915
-
1916
- // The ones that are only literal across a whole document (title case, heading levels, boldface density, thematic breaks, mixed apostrophes) are the structural checks in `slop.js`;
1917
-
1918
- // the machine residue is `artifacts` below. Both languages, because the French page (fr:Aide:Identifier l'usage d'une IA générative) names the same signs and a draft can be in either.
1919
- {
1920
- id: "superficial-ing-clause",
1921
- name: "Superficial -ing analysis",
1922
- // A comma, then one of a closed set of participles, then a determiner.
1923
-
1924
- // The determiner is what keeps it one-directional: "..., reflecting on it" and "..., ensuring we ship" have no determiner and read clean,
1925
-
1926
- // while "..., highlighting the importance of X" is the shape every time.
1927
- test: /,\s+(?:highlighting|underscoring|emphasi[sz]ing|showcasing|reflecting|symboli[sz]ing|cementing|solidifying|illustrating|demonstrating|reinforcing|signal(?:l)?ing|marking|contributing to|ensuring)\s+(?:the|its|his|her|their|a|an|how|why|that)\b/i,
1928
- rule: "A trailing participial clause that restates the sentence as significance instead of adding a fact. The lint half of the `superficial-ing-analysis` shape. Cut the clause, or replace it with the fact it was standing in for.",
1929
- example:
1930
- '"..., highlighting the importance of clear processes." / "..., underscoring its role in the region."',
1931
- },
1932
- {
1933
- id: "superficial-ing-clause-fr",
1934
- name: "Clause participiale creuse",
1935
- // The French form of the same shape. The participle set is closed and each
1936
- // one is rare outside this construction, so the determiner is not needed to
1937
- // keep it one-directional.
1938
- test: /,\s+(?:soulignant|mettant en (?:lumière|avant|évidence)|illustrant|témoignant|reflétant|renforçant|marquant|démontrant|confirmant|consacrant|contribuant|permettant ainsi)\b/i,
1939
- rule: "La même forme en français : une virgule puis un participe présent qui commente la phrase au lieu d'ajouter un fait. Coupez la clause ou remplacez-la par le fait qu'elle remplaçait.",
1940
- example:
1941
- '"..., soulignant l\'importance de la démarche." / "..., témoignant d\'un savoir-faire reconnu."',
1942
- },
1943
- {
1944
- id: "copula-avoidance",
1945
- name: "Copula avoidance",
1946
- // WP:AINOCOPULA. A closed set of verbs standing in for "is".
1947
-
1948
- // Each one takes a determiner straight after, which is what an ordinary "he stands as the last witness" does not do often enough to matter,
1949
-
1950
- // and "the server operates as a proxy" is the one real use the set deliberately excludes by requiring the abstract nouns after `represents` and `marks`.
1951
- test: /\b(?:serves|stands|functions|acts)\s+as\s+(?:a|an|the)\b|\brepresents\s+a\s+(?:shift|significant|major|departure|milestone|turning)\b|\bmarks\s+(?:a|the)\s+(?:beginning|start|first|shift|turning|new)\b/i,
1952
- rule: 'A verb hired to avoid writing "is". Wikipedia measured a 10% drop in "is" and "are" in academic writing the year the chatbots landed, and this is where it went. Write "is", or write the verb that says what the thing actually does.',
1953
- example:
1954
- '"Gallery 825 serves as the exhibition arm." / "The launch marks a turning point." / "It stands as a vibrant town."',
1955
- },
1956
- {
1957
- id: "copula-avoidance-fr",
1958
- name: "Évitement de la copule",
1959
- test: /\b(?:s'impose|se pose|s'affirme|se présente|se veut)\s+comme\s+(?:un|une|le|la|l')\b|\bconstitue\s+(?:un|une)\s+(?:tournant|jalon|étape|pilier|témoignage|référence)\b/i,
1960
- rule: 'Un verbe employé pour ne pas écrire "est". Écrivez "est", ou le verbe qui dit ce que la chose fait vraiment.',
1961
- example:
1962
- '"La plateforme s\'impose comme une référence." / "Ce lancement constitue un tournant."',
1963
- },
1964
- {
1965
- id: "notability-claim",
1966
- name: "Canned notability claim",
1967
- // WP:OVERATTRIBUTION. A coverage verb, then a quantifier or a media-class
1968
- // word rather than a named outlet. A named source ("featured in Le Monde")
1969
- // has neither and reads clean.
1970
- test: /\b(?:featured|profiled|covered|cited|mentioned|recognized|recognised)\s+in\s+(?:multiple|numerous|several|various|major|leading|top|national|regional|international|independent|respected|widely)\b|\b(?:maintains?|has)\s+an?\s+active\s+(?:social media|online)\s+presence\b/i,
1971
- rule: "Notability asserted by describing the sources rather than saying what they reported. Name the outlet and what it said, or drop the sentence.",
1972
- example:
1973
- '"Profiled in multiple independent outlets." / "He maintains an active social media presence."',
1974
- },
1975
- {
1976
- id: "notability-claim-fr",
1977
- name: "Notoriété affirmée",
1978
- test: /\b(?:cité|mentionné|présenté|couvert|repris)e?s?\s+(?:dans|par)\s+(?:de nombreux|plusieurs|divers|différents|les principaux|de multiples)\b|\bprésence active sur les réseaux\b/i,
1979
- rule: "La notoriété affirmée en décrivant les sources au lieu de dire ce qu'elles ont rapporté. Nommez le média et ce qu'il a écrit, ou supprimez la phrase.",
1980
- example: '"Cité dans de nombreux médias nationaux."',
1981
- },
1982
- {
1983
- id: "challenges-outlook",
1984
- name: "Despite these challenges",
1985
- // WP:FACESCHALLENGES. The formula, not the word. "the challenges are real"
1986
- // has no `despite` in front of it and does not match.
1987
- test: /\bdespite\s+(?:its|these|those|the|such|ongoing)\s+(?:[a-z]+\s+){0,2}(?:challenges|limitations|drawbacks|setbacks|obstacles|hurdles|criticisms?)\b|\bfaces?\s+(?:several|a number of|numerous|various|many|its own)\s+(?:challenges|hurdles|obstacles)\b/i,
1988
- rule: "The closing paragraph that concedes a difficulty in order to end on an upswing. It states nothing checkable in either half. Write the difficulty and what happens because of it, or write neither.",
1989
- example:
1990
- '"Despite its rapid growth, the sector faces several challenges." / "Despite these challenges, it continues to thrive."',
1991
- },
1992
- {
1993
- id: "challenges-outlook-fr",
1994
- name: "Malgré ces défis",
1995
- test: /\bmalgré\s+(?:ces|ses|les|un|de)\s+(?:[a-zà-ÿ]+\s+){0,2}(?:défis|limites|obstacles|difficultés|critiques|freins)\b|\bfait face à\s+(?:plusieurs|de nombreux|divers|certains)\s+(?:défis|obstacles|difficultés)\b/i,
1996
- rule: "Le paragraphe de clôture qui concède une difficulté pour finir sur une note positive. Écrivez la difficulté et sa conséquence, ou aucune des deux.",
1997
- example: '"Malgré ces défis, le secteur continue de croître."',
1998
- },
1999
- {
2000
- id: "formulaic-heading",
2001
- name: "Formulaic section heading",
2002
- // WP:AILEGACY and the fr page's "Conclusion / Héritage" sign. A whole markdown heading, anchored at both ends, so a sentence that happens to contain "conclusion" does not match.
2003
-
2004
- // `## Legacy` on its own is included: a bare abstract noun as a heading is the sign.
2005
- test: /^#{1,6}\s*(?:awards? and recognition|recognition and awards?|challenges and (?:legacy|opportunities|future prospects)|future (?:outlook|prospects|directions)|legacy and impact|impact and legacy|significance and legacy|conclusion|legacy|overview|key takeaways?|final thoughts?|héritage|conclusion et perspectives|perspectives|perspectives d'avenir|prix et distinctions|défis et perspectives|points clés|en résumé)\s*$/im,
2006
- rule: "A section heading from the outline a model reaches for when it has run out of subject. The section under it is always summary rather than fact. Delete the section, or retitle it after the one thing it actually says.",
2007
- example: '"## Awards and recognition" / "## Future Outlook" / "## Conclusion" / "## Héritage"',
2008
- },
2009
- {
2010
- id: "question-heading",
2011
- name: "Question as a heading",
2012
- // The fr page's "titres de sections sous forme de question".
2013
-
2014
- // A heading is a label, so the question mark is the whole signature and no exception is needed: an FAQ entry is a question in the body,
2015
-
2016
- // not in the outline.
2017
- view: "faqless",
2018
- test: /^#{1,6}\s+[^\n?]{5,90}\?\s*$/m,
2019
- rule: "A section heading written as a question the writer then answers. It buys a beat of suspense the reader did not ask for and it makes the outline unscannable. Name the answer in the heading.",
2020
- example: '"## Why does this matter?" / "## Qu\'est-ce que le pilotage ?"',
2021
- },
2022
- {
2023
- id: "inline-header-list",
2024
- name: "Inline-header vertical list",
2025
- // WP:AILIST. A bullet or a number, a bold run, then a colon, on either side of the closing stars because a chatbot writes it both ways.
2026
-
2027
- // The colon is required: a list of bold link labels with no colon is ordinary markdown.
2028
- test: /^[ \t]*(?:[-*+•–—]|\d+[.)])\s+\*\*[^*\n]{2,60}(?:[::]\*\*|\*\*\s*[::])/m,
2029
- rule: "The bullet, bold label, colon, sentence shape a chatbot renders by default. It turns prose into a specification nobody asked for and the bold adds no emphasis because every line has it. Write the paragraph, or drop the bold and the colon.",
2030
- example:
2031
- '"- **Route Details**: Starts at Medak and ends at Bhainsa." / "1. **Recommended:** use the shorter form."',
2032
- },
2033
- {
2034
- id: "placeholder-text",
2035
- name: "Unfilled placeholder",
2036
- // WP:AIPLACEHOLDER. A bracketed fill-in-the-blank, a parenthesised instruction to the writer, or a date field the model could not resolve.
2037
-
2038
- // `x` and `y` are deliberately not accepted as bracket words, because `- [x]` is a task list.
2039
-
2040
- // The bracket cannot follow an identifier or a `)` either, because TypeScript indexes a type that way: `(typeof locales)[number]` read as an unfilled `[number]`, 15 Sep 2026.
2041
- test: /(?<![\w)\]])\[(?:your|insert|inserez|insérez|add|ajouter|name|nom|company|société|client|product|produit|brand|marque|topic|sujet|entertainer|artist|city|ville|date|number|tbd|todo|placeholder)\b[^\]\n]{0,40}\]|\((?:add|insert|ajoutez|insérez)\b[^)\n]{0,40}(?:here|ici|if available|si disponible)\)|\b20\d\d-(?:XX|xx)-(?:XX|xx)\b/i,
2042
- rule: "A template blank the writer never filled in. It is the one sign on this list that is proof rather than evidence: nobody types a bracketed field name into finished copy.",
2043
- example: '"[Entertainer\'s Name]" / "(Add your channel URL here)" / "access-date=2025-xx-xx"',
2044
- },
2045
- {
2046
- id: "definitional-lead",
2047
- name: "Title as a proper noun",
2048
- // A lead sentence that defines its own headline instead of the thing.
2049
-
2050
- // The anchor is a line start plus a capital, so an ordinary mid-paragraph "the term refers to a shorthand" does not match.
2051
-
2052
- // The second branch is the list article that reads its own title as a noun, which "Paris is a city" is not,
2053
-
2054
- // so the branch starts at "List of" and nowhere else.
2055
- test: /^["'“]?[A-Z][^.\n]{2,60}["'”]?\s+(?:refers to|is the term for|désigne)\s+(?:the|a|an|le|la|un|une|l')\b|^(?:List of|Liste des?) [^.\n]{3,60}\s+(?:is|est)\s+(?:a|an|un|une)\b/m,
2056
- rule: 'A lead that treats its own title as a thing in the world and defines the words rather than the subject. Write about the subject: "The catchment area of a hospital is ..." rather than "Catchment area (health) refers to ...".',
2057
- example:
2058
- '"Catchment area (health) refers to the geographic area from which ..." / "List of songs about Mexico is a curated compilation ..."',
2059
- },
2060
- {
2061
- id: "sentence-not-pivot",
2062
- name: "Sentence pivot",
2063
- // The full-stop form of `negation-pivot`, which `comma-not-pivot` cannot see.
2064
-
2065
- // A sentence opening on a denial, then a sentence asserting what the thing is, is the same swap with a period doing the comma's work.
2066
-
2067
- // The follow-on has to be definitional (`It is`, `That is`) and must not itself be a denial, so "No client asked. It is not urgent either" does not match.
2068
- test: /(?:^|[.!?]\s+)(?:No|Nothing|Nobody)\s+[^.!?\n]{2,70}[.!?]\s+(?:It|That|This)(?:'s|’s|\s+is)\s+(?!not\b)/u,
2069
- rule: "A denial standing in for a statement, split across two sentences. State what the thing is and let the contrast be implied.",
2070
- example:
2071
- '"No video generator made this. It is code." / "Nothing was automated here. That is the point." / "Nobody wrote the copy. It is a template."',
2072
- },
2073
- {
2074
- id: "elliptical-flip",
2075
- name: "This one doesn't",
2076
- // Ramzi, 23 Sep 2026. 3 hits across all first-party copy, 0 in his transcripts.
2077
- test: new RegExp(
2078
- `${SENTENCE_OPEN}(?:(?:This|That|These|Those)(?:\\s+(?:one|ones|part|bit|lesson|course|step|time|video|post|page|room|piece|tool|kind|way|version|week|email))?|Mine|Yours|Ours|Theirs)\\s+(?:(?:does|do|did|is|are|was|were|will|would|can|could|should|has|have|had|isn|aren|wasn|weren|doesn|don|didn|hasn|haven|hadn|wouldn|couldn|shouldn)(?:n['’]t|\\s+not)?|cannot|won['’]t|can['’]t)[.!]`,
2079
- "u",
2080
- ),
2081
- rule: 'A broad claim, then a 3-word sentence that flips it with a pointer and a bare verb: "Most of it sits behind an install. This part doesn\'t." It\'s the negation pivot with the second half cut off, and it reads as a reveal. Say what the thing is: "You can do this part without installing anything."',
2082
- example:
2083
- '"Most of what I teach sits behind an install. This part doesn\'t." / "Most tools guess. This one doesn\'t." / "Should an agent write to a client record? Mine does."',
2084
- },
2085
- {
2086
- id: "watching-metadiscourse",
2087
- name: "Telling the reader what they are doing",
2088
- // Interpretive metadiscourse aimed at the artefact in front of the reader.
2089
-
2090
- // Scoped to a determiner so "you are watching closely" and "you are seeing fewer replies" do not match: the tell is pointing at the thing on screen and narrating the
2091
-
2092
- // act of looking at it.
2093
- test: /\byou(?:'re|’re|\s+are)\s+(?:watching|looking\s+at|seeing|reading)\s+(?:the|a|an|this|that|my|our)\b/i,
2094
- rule: "A line that narrates the reader's own act of looking instead of saying the thing. Cut the frame and keep the fact.",
2095
- example:
2096
- '"You are watching the second attempt." / "You\'re looking at the rebuild." / "You are reading the third draft."',
2097
- },
2098
- {
2099
- id: "once-you-law",
2100
- name: "Hypothetical law",
2101
- // The advisory aside dressed as a rule of nature: a condition the writer invented, then a consequence the reader is told they will feel.
2102
-
2103
- // Anchored on "Once you" plus a second-person consequence verb, so an ordinary "Once you have the invoice, send it" does not match.
2104
- test: /\bOnce\s+you(?:'ve|’ve)?\s+(?:have\s+|had\s+)?\w+[^.!?\n]{0,60}?,?\s+you\s+(?:never|no longer|stop|start|realise|realize|understand|see)\b/i,
2105
- rule: "A law about what the reader will feel, invented one clause earlier. Say the fact and let the reader draw the consequence.",
2106
- example:
2107
- '"Once you have seen the restaurant you stop asking what it is." / "Once you understand the model, you never go back." / "Once you\'ve run it, you realise the rest is noise."',
2108
- },
2109
- {
2110
- id: "the-x-that-y-headline",
2111
- name: "The X that Y",
2112
- // A whole line that is nothing but "The [noun phrase] that [clause]", anchored per-line so an ordinary mid-paragraph relative clause ("the file that changed is small") does not match:
2113
-
2114
- // a title or a card label sits alone on its line, and this only fires when that entire line is the construction.
2115
- test: /^\s*(?:#{1,6}\s+)?The\s+(?:[A-Za-z][\w'-]*\s+){1,6}that\s+(?:[A-Za-z][\w'-]*\s+){1,8}[A-Za-z][\w'-]*[.!?]?\s*$/im,
2116
- rule: 'A headline or card title built as "The [noun] that [clause]": the noun is named, then a relative clause delivers the payoff. It is a title formula, not a sentence anyone would say, and it repeats itself the moment two of them sit near each other. Ramzi, 14 Sep 2026, on "The fifth ask that cost me nothing": "This is slop. The XX that Is an anti pattern." Say the payoff as the title and drop the frame: "Zero-cost on the fifth ask."',
2117
- example:
2118
- '"The fifth ask that cost me nothing" / "The favor that stopped eating my week" / "The handover that leaves no loose thread"',
2119
- },
2120
- {
2121
- id: "before-it-happens-countdown",
2122
- name: "Before it happens again",
2123
- // A closing imperative racing a recurrence: "before it happens again" or "before it happens a 4th time".
2124
-
2125
- // The ordinal or "again" is required, so an ordinary "finish it before it happens" (a real deadline, no recurrence) does not match.
2126
- test: /\bbefore\s+it\s+happens\s+(?:again|(?:a\s+)?(?:\d+(?:st|nd|rd|th)|another)(?:\s+time)?)\b/i,
2127
- rule: 'A closing line staged as a countdown to a recurrence nobody was tracking, for tension rather than fact. Ramzi, 14 Sep 2026, on "Write each one down before it happens a 4th time": "Same thing here. XXX before it happens or whatever." Say when to do the thing: "Write it down the next time it comes up."',
2128
- example:
2129
- '"Write each one down before it happens a 4th time." / "Fix the root cause before it happens again."',
2130
- },
2131
- {
2132
- id: "universal-so-payoff",
2133
- name: "Every X, so Y",
2134
- // A universal quantifier ("Every"/"All") stating a generalization, then a
2135
- // comma-"so" clause delivering a tidy payoff. Bounded to one sentence so
2136
- // it cannot cross a paragraph and pair two unrelated claims.
2137
- test: /\b(?:Every|All)\s+[^.!?\n]{3,60},\s+so\s+[^.!?\n]{3,60}[.!?]/i,
2138
- rule: 'A generalization capped with a neat "so" consequence in the same breath, reads as a thesis statement rather than something said. Ramzi, 14 Sep 2026, on "Every agency meets the same 7, so nobody improvises the 5th ask": flagged as the same anti-pattern, on a run of feedback he said he has repeated for weeks. Split it: state the fact, then the consequence as its own plain sentence.',
2139
- example:
2140
- '"Every agency meets the same 7, so nobody improvises the 5th ask." / "All 6 templates ship the same way, so nobody argues about the steps."',
2141
- },
2142
- {
2143
- id: "how-adj-subject-verb-final",
2144
- name: "How busy the day is",
2145
- // "no matter how [adjective] [noun phrase] is/are/was/were": the adjective fronts for the "how" question shape and strands the subject and its verb at the very end of the clause,
2146
-
2147
- // which is not how the sentence would be said out loud. Scoped to "no matter how" so an ordinary question ("how busy is the day?") does not match.
2148
- test: /\bno matter how\s+\w+\s+(?:the|a|an|this|that|your|my|our|his|her|their)\s+[\w'-]+(?:\s+[\w'-]+){0,2}\s+(?:is|are|was|were|gets)\b/i,
2149
- rule: 'The adjective fronts to ask "how", and the subject and its verb end up stranded as the last words of the sentence instead of leading it. Ramzi, 14 Sep 2026, on "no matter how busy the day is": "You have put the subject and the verb as the last word of the sentence." Put the subject first: "even on a busy day" or "however busy the day gets" restructured so the verb is not the clause\'s last word.',
2150
- example:
2151
- '"no matter how busy the day is" / "no matter how tight the deadline was" / "no matter how loud the room gets"',
2152
- },
2153
- {
2154
- id: "paired-copula",
2155
- name: "X is the A, Y is the B",
2156
- // Two "is the" clauses on ONE line, the second riding on the first.
2157
-
2158
- // The second subject is at most two words and cannot open on a conjunction, which is what separates the aphorism from an ordinary joined sentence:
2159
-
2160
- // "the rate is the cost, and the volume is the driver" reads as speech and does not match. Same line only, so two unrelated paragraphs cannot pair.
2161
- test: /\b(?:is|are)[ \t]+the[ \t]+[a-zà-ÿ-]+[ \t]*[.;,][ \t]+(?!(?:and|but|so|or|yet|while|because|when|if|which|that|then)\b)(?:the[ \t]+|a[ \t]+|an[ \t]+)?[a-zà-ÿ-]+(?:[ \t]+[a-zà-ÿ-]+)?[ \t]+(?:is|are)[ \t]+the\b/i,
2162
- rule: "Two copulas in a row, each assigning one noun to another, written for the balance rather than to say a second thing. Ramzi, 15 Sep 2026, on the CBAM news page. Keep the clause that carries the fact and delete the one that mirrors it.",
2163
- example:
2164
- '"News is the signal. The dataset is the answer." / "The diff is the product, the version is the receipt."',
2165
- },
2166
- {
2167
- id: "elided-passive",
2168
- name: "X built for Y",
2169
- // Headline grammar: subject, participle, preposition, no auxiliary. Measured 17 Sep 2026: 0 hits on 190 of his posts, 27 on the website and app strings.
2170
- test: new RegExp(
2171
- `(?:^|["'\`]|#{1,6}[ \\t])[ \\t]*${SUBJECT_STOP}[A-Z0-9][\\w&'’.-]*(?:[ \\t]+${NOUN_PHRASE_STOP}(?!${PARTICIPLE}\\b)[\\w&'’-]+){0,3}[ \\t]+${INTRANSITIVE_PAST}${PARTICIPLE}[ \\t]+${PREPOSITION}\\b(?:(?!\\b${FINITE_AUXILIARY}\\b)[^.!?\\n"'\`<>]){0,60}[.!]?(?=[ \\t]*(?:["'\`]|$(?![\\r\\n][ \\t]*[a-z])))`,
2172
- "m",
2173
- ),
2174
- rule: 'A subject, then a past participle standing in for the verb, then a preposition, with the auxiliary dropped. It is newspaper headline grammar: nothing happens in it and nobody does it. Ramzi, 17 Sep 2026, on a deck cover that passed the gate: "ClickUp rebuilt around your cases". Write the sentence with a doer and a finite verb: "We rebuild ClickUp around your cases."',
2175
- example:
2176
- '"ClickUp rebuilt around your cases" / "Scenarios built on your own stack" / "4 hours saved on each"',
2177
- },
2178
- {
2179
- id: "parallel-clauses",
2180
- name: "X does the A, Y does the B",
2181
- // Isocolon: two clauses cut to one build (subject, present verb, object) side by side. Widens `paired-copula` past "is the".
2182
- test: new RegExp(
2183
- `(?:^|[.!?:]["'’”)]?[ \\t]+|["'\`\\n])[ \\t]*${CLAUSE_SUBJECT}[ \\t]+${PRESENT_VERB}[ \\t]+${OBJECT_DETERMINER}(?:[ \\t]+[\\w'’-]+){0,2}[ \\t]*[,;.][ \\t]+(?:and[ \\t]+)?${CLAUSE_SUBJECT}[ \\t]+${PRESENT_VERB}[ \\t]+${OBJECT_DETERMINER}\\b`,
2184
- "m",
2185
- ),
2186
- rule: 'Two or more clauses built the same way (subject, present verb, object) and set side by side for the balance. The symmetry carries the message, each clause says less than it would alone, and a third member usually arrives longer as a crescendo. Ramzi, 17 Sep 2026, on "Clio keeps the record, ClickUp runs the work, and Maz reads it all on one dashboard." Keep the clause that carries the new fact and fold the others into it.',
2187
- example:
2188
- '"Clio keeps the record, ClickUp runs the work, and Maz reads it all on one dashboard." / "One builds the workspace, the other runs the week inside it." / "The diff shows the change. The version keeps the receipt."',
2189
- },
2190
- {
2191
- id: "for-any-tail",
2192
- name: "..., for any X",
2193
- // A question or an inquisitive imperative, then a comma and a universal scope bolted on as a closer.
2194
-
2195
- // The opener set is closed and the tail is `for` plus a quantifier, so "it is priced in euros, for each importer" (no opener),
2196
-
2197
- // "know what it costs for any code" (no comma) and "what the calendar says, in one line" (a count, not a scope) all read clean.
2198
- test: /\b(?:know|see|find out|learn|discover|check|understand|what|which|how)\b[^.!?\n]{2,60},[ \t]*for[ \t]+(?:any|every|each|one)\b/i,
2199
- rule: "A headline that asks something, then hangs a scope claim off a comma to cover the whole catalogue. The scope is a specification, not a clause. Ramzi, 15 Sep 2026, on the CBAM home and calculator headlines. Fold it into the sentence or make it its own line.",
2200
- example:
2201
- '"Know what CBAM costs you, for any CN code." / "What CBAM costs you, for one CN code."',
2202
- },
2203
- {
2204
- id: "before-you-verb-it",
2205
- name: "X before you Y it",
2206
- // A whole line that is a noun, then a second-person clause telling the reader when they are allowed to act.
2207
-
2208
- // Anchored per line and to the line's end, so an ordinary "read the terms before you sign it" inside a paragraph is left alone:
2209
-
2210
- // this only fires on the heading shape.
2211
- test: /^[ \t]*(?:#{1,6}[ \t]+)?[A-Z][^.!?\n]{0,40}[ \t]+before[ \t]+you[ \t]+[a-zà-ÿ]{2,12}[ \t]+(?:it|them|one)[ \t]*[.!?]?[ \t]*$/m,
2212
- rule: "A heading that stages the reader's own action as a gate, in the second person, so the section reads as permission rather than as what it holds. Ramzi, 15 Sep 2026, on the CBAM FAQ heading. Name what is in the section.",
2213
- example: '"Questions before you use it" / "What to check before you ship it"',
2214
- },
2215
- {
2216
- id: "interrogative-heading",
2217
- name: "What the answer is built on",
2218
- // A whole line opening on an interrogative and ending on a verb, with no question mark: the heading asks the section's own question instead of naming what is in it.
2219
-
2220
- // Distinct from `question-heading`, which needs the `?`.
2221
-
2222
- // The trailing lookahead drops a hard-wrapped paragraph whose next line continues in lower case, and a line that ends in `.` is a sentence,
2223
-
2224
- // not a heading, so it never reaches the anchor.
2225
- test: /^[ \t]*(?:#{1,6}[ \t]+)?(?:\d+ • )?(?:What|How|Where|Which|Why|When|Who)[ \t]+(?:[A-Za-zà-ÿ0-9][\w'’-]*[ \t]+){1,9}[a-zà-ÿ0-9][\w'’-]*[ \t]*$(?!\n[ \t]*[a-zà-ÿ])/m,
2226
- rule: 'A heading that restates the section as a question the reader did not ask, then leaves the answer to the body. Ramzi, 15 Sep 2026, on the CBAM calculator page, and 23 Sep 2026 on a Skool lesson card titled "What you take away from lesson 4". Name what the section holds.',
2227
- example: '"What the answer is built on" / "What Annex I covers" / "How the dataset is built"',
2228
- },
2229
- {
2230
- id: "positioned-noun-heading",
2231
- name: "The X beside the Y",
2232
- // A whole line made of two noun phrases and a position word, with no verb.
2233
-
2234
- // Per line and anchored both ends, like `the-x-that-y-headline`, so the same words inside a sentence ("the rule beside the field is cited") are untouched.
2235
- test: /^[ \t]*(?:#{1,6}[ \t]+)?The[ \t]+[a-zà-ÿ-]+[ \t]+(?:beside|behind|beneath|below|above|under|over|inside|within|alongside|around|between|next[ \t]+to|across[ \t]+from|in[ \t]+front[ \t]+of|on[ \t]+top[ \t]+of)[ \t]+(?:the|its|your|each)[ \t]+[a-zà-ÿ-]+[ \t]*[.!?]?[ \t]*$/m,
2236
- rule: "A card title that places one noun next to another and stops, with no verb and nothing asserted. Ramzi, 15 Sep 2026, on the CBAM home cards. Say what the thing does where it sits.",
2237
- example: '"The rule beside the field" / "The source behind each number"',
2238
- },
2239
- {
2240
- id: "the-x-follows",
2241
- name: "When X changes, the Y follows",
2242
- // A "when" clause, a comma, then the product as the subject of a bare reaction verb that ends the sentence.
2243
-
2244
- // The verb must close the sentence, so "the API follows the weekly price" or "and the API follows it" passes.
2245
- test: /\bwhen[ \t]+[^,.!?\n]{2,50},[ \t]*(?:the|our|your)[ \t]+[\w'’-]+[ \t]+(?:follows|adapts|keeps[ \t]+up|keeps[ \t]+pace|responds|moves[ \t]+with[ \t]+it)[ \t]*[.!]/i,
2246
- rule: 'A headline that casts a regulator as an actor and the product as its shadow, which reads as a slogan and never says what the product is. Ramzi, 16 Sep 2026, on the CBAM home headline: "too pompous". Name the category: what it is and what it is for.',
2247
- example:
2248
- '"When Brussels changes CBAM, the API follows." / "When the market moves, our data keeps up."',
2249
- },
2250
- // --- 17 Sep 2026. Three shapes named off one cold sales email, which opened "42 skills across seven folders" about a repo holding 26.
2251
-
2252
- // One fault under all three: the sentence drops the element that would let a reader check it.
2253
-
2254
- // The count has no verb, so nobody counted; the promise names the drawback and not the mechanism; the benefit names the reader's absence and not the work.
2255
-
2256
- // Ramzi the same day, setting how they had to be written: "think about the heuristic of the grammar so that the rule is strong enough",
2257
-
2258
- // "understand the first principles of the grammatical choice to fix the root cause".
2259
- {
2260
- id: "bare-count-clause",
2261
- name: "N things across M things",
2262
- /**
2263
- * Two counts, a distributive preposition, and no verb: a measurement parked where the predicate belongs.
2264
- */
2265
-
2266
- /*
2267
- * The preposition set is closed to the three that can ONLY distribute.
2268
- */
2269
-
2270
- /*
2271
- * `over` and `in` were measured and dropped: "159 comments and over 7,000 likes" and "28 emails over 10 days" are a comparative and a duration, and neither is this shape.
2272
- */
2273
-
2274
- /*
2275
- * The clause has to CLOSE on a comma, a stop or "and", which is what leaves a verb out: "627 transcripts across 13 channels put the winner ahead" has a
2276
- */
2277
-
2278
- /*
2279
- * predicate and passes.
2280
- */
2281
-
2282
- /*
2283
- * 7 hits across 190 posts and 1,458 files, every one of them the shape.
2284
- */
2285
- test: new RegExp(
2286
- `(?:^|[.!?:;]["'’”)\\]]?\\**[ \\t]+|\\n)[ \\t]*\\**${COUNT}[ \\t]+(?:[a-zà-ÿ-]+[ \\t]+){0,2}[a-zà-ÿ]{3,}[ \\t]+(?:across|spanning|throughout)[ \\t]+${COUNT}[ \\t]+(?:[a-zà-ÿ-]+[ \\t]+){0,2}[a-zà-ÿ]{3,}\\**(?=[,.;!?]|[ \\t]+and[ \\t]|[ \\t]*\\n|[ \\t]*$)`,
2287
- ),
2288
- rule: 'A count, a second count, and no verb between them. Breadth stands in for the claim, and because nobody is said to have counted anything the number is never checked: the email that named this wrote "42 skills across seven folders" about a repo that shipped 26 in 6. Give the count a doer and a verb, and the reader can test it: "I counted 270 frames on ten channels", "the pack holds 86 face plates in 26 expressions".',
2289
- example:
2290
- '"42 skills across seven folders." / "30 agents across nine business areas." / "270 frames across ten channels, each split into two bands."',
2291
- },
2292
- {
2293
- id: "promise-minus-drawback",
2294
- name: "X without the Y",
2295
- /**
2296
- * A noun phrase, a privative `without`, and still no verb. The hair-dye frame: "colour without the ammonia".
2297
- */
2298
-
2299
- /*
2300
- * Three things keep it off ordinary English, and each was measured.
2301
- */
2302
-
2303
- /*
2304
- * The head noun cannot end in `s`, `d` or `ing`, so a finite verb in that slot fails ("The build runs without the dev server").
2305
- */
2306
-
2307
- /*
2308
- * No auxiliary may sit in the filler, so a copula fails ("The output is right without the correction").
2309
- */
2310
-
2311
- /*
2312
- * And the `without` phrase has to end the clause, so a predicate after it fails ("A feature tour without the claim line is a screen recording").
2313
- */
2314
-
2315
- /*
2316
- * 0 hits across 190 posts and 1,458 files.
2317
- */
2318
- test: new RegExp(
2319
- `${SENTENCE_OPEN}\\**(?:[Aa]ll[ \\t]+the|[Tt]he|[Aa]|[Aa]n|[Yy]our|[Oo]ur|[Ee]very)[ \\t]+(?:(?!without[ \\t])(?!${FINITE_AUXILIARY}[ \\t])[a-zà-ÿ-]+[ \\t]+){0,3}[a-zà-ÿ]{2,}(?<![sd])(?<!ing)[ \\t]+without[ \\t]+(?:the|a|an|any)[ \\t]+(?:[a-zà-ÿ-]+[ \\t]+){0,2}[a-zà-ÿ-]{3,}\\**[ \\t]*(?=[,.;!?]|[ \\t]*\\n|$)`,
2320
- ),
2321
- rule: "A thing offered, then the drawback it does not have, and nothing about how. It is the negation pivot sold as a benefit: the reader learns what is absent, never what is present, and a competitor's weakness carries the sentence instead of the product. Say what it does. If the missing drawback is the point, name the mechanism that removes it.",
2322
- example:
2323
- '"A hair colour change without the ammonia." / "All the power without the complexity." / "The reach of an agency without the retainer."',
2324
- },
2325
- {
2326
- id: "absentee-benefit",
2327
- name: "While you sleep",
2328
- /**
2329
- * The work described as happening in the reader's absence, which is the value the sentence offers instead of a mechanism.
2330
- */
2331
-
2332
- /*
2333
- * Second person is required throughout, because the state words are ordinary on their own: Ramzi's own 2023 post, "90% is on autopilot until I start the client project",
2334
- */
2335
-
2336
- /*
2337
- * is a bounded fact about a system and is spared.
2338
- */
2339
-
2340
- /*
2341
- * "so you do not have to" needs the clause to END there, for the same reason: the ellipsis IS the fault, and naming the work makes the sentence informative ("so
2342
- */
2343
-
2344
- /*
2345
- * you do not have to open it").
2346
- */
2347
- test: new RegExp(
2348
- `\\bwhile[ \\t]+you(?:[ \\t]+(?:are|'re|’re))?[ \\t]+(?:sleep\\w*|asleep|rest\\w*|relax\\w*|away|off|out|do[ \\t]+nothing|focus[ \\t]+on|get[ \\t]+on[ \\t]+with)\\b` +
2349
- `|\\bin[ \\t]+your[ \\t]+sleep\\b` +
2350
- `|\\b(?:you|your)\\b[^.!?\\n]{0,60}\\bon[ \\t]+autopilot\\b|\\bon[ \\t]+autopilot\\b[^.!?\\n]{0,60}\\b(?:you|your)\\b` +
2351
- `|\\bset[ \\t]+it[ \\t]+and[ \\t]+forget[ \\t]+it\\b` +
2352
- `|\\bso[ \\t]+you[ \\t]+(?:do[ \\t]*not|don'?t|never|no[ \\t]+longer)[ \\t]+have[ \\t]+to[ \\t]*(?=[.!?,;]|[ \\t]*$)`,
2353
- "i",
2354
- ),
2355
- rule: 'The benefit stated as the reader\'s absence. It says when the work happens and never what does it, so the sentence cannot be wrong and cannot be checked, and it carries the passive-income register every ad in the category uses. Ramzi, 17 Sep 2026, on "A calendar takes them while you sleep": the subject is an abstraction and "while you" is slop. Name what runs and what it does: "the booking page writes the event to your calendar".',
2356
- example:
2357
- '"A calendar takes them while you sleep." / "It books the call while you focus on the work." / "Your pipeline runs on autopilot." / "The agent files them so you do not have to."',
2358
- },
2359
- // --- 18 Sep 2026.
2360
-
2361
- // Named off a demo-page caption, "2 minutes, sound on.", that passed the gate clean: the fault is `comma-hung-fragment`, and that shape is in `shapes` because an imperative and a noun
2362
-
2363
- // are the same token to a regex ("sound on" against "turn the sound on").
2364
-
2365
- // A duration is the sub-case where the token cannot be a verb, so the missing predicate is decidable.
2366
- {
2367
- id: "bare-duration-clause",
2368
- name: "N minutes, no verb",
2369
- /**
2370
- * A count, a time unit, a comma, and no verb on either side of it.
2371
- */
2372
-
2373
- /*
2374
- * A duration noun is never an imperative, so the head has no predicate by construction.
2375
- */
2376
-
2377
- /*
2378
- * The comma is what makes it decidable: a real adverbial opener carries its preposition ("In 2 minutes, the site is live") and fails on the first token,
2379
- */
2380
-
2381
- /*
2382
- * and a real second clause carries a subject and a finite verb, both of which `TAIL_WORD` forbids.
2383
- */
2384
-
2385
- /*
2386
- * Three exclusions, each measured over 20,860 files. A tail may not open on a conjunction, because "2 minutes, and you are done" is a coordination; nor on a second count,
2387
- */
2388
-
2389
- /*
2390
- * because "3 years, 2 months" and "Four days, five" are lists; and the clause has to close on a stop rather than a newline,
2391
- */
2392
-
2393
- /*
2394
- * because markdown prose here is hard-wrapped and a line ending in "four weeks, the" is the middle of a sentence. 12 hits left, every one the shape.
2395
- */
2396
- test: new RegExp(
2397
- `${SENTENCE_OPEN}\\**${COUNT}[ \\t]+${DURATION}\\**[ \\t]*,[ \\t]+` +
2398
- `(?!(?:and|or|but|so|then|which|that|who|because|if|while|until)[ \\t])` +
2399
- `(?!(?:\\d|${COUNT})(?![\\w'’-]))` +
2400
- `(?:${TAIL_WORD}[ \\t]+){0,2}${TAIL_WORD}\\**[ \\t]*(?=[.!?]|[ \\t]*$)`,
2401
- "i",
2402
- ),
2403
- rule: 'A length of time parked where the predicate belongs. The sentence measures something and never says what, so there is nothing in it a reader can agree or disagree with, and the duration reads as a label on a button rather than a fact about the thing. Give the duration a subject and a verb, or fold it into the sentence next to it: "It runs 2 minutes, so turn the sound on", "The call takes 20 minutes".',
2404
- example: '"2 minutes, sound on." / "Three days, tops." / "20 minutes, no slides."',
2405
- },
2406
- {
2407
- id: "stop-opener",
2408
- // Sentence-initial "Stop", bare, no "start"/"begin" pairing (that shape is
2409
- // `stop-start`). Case-sensitive so mid-sentence "stop" ("when you stop
2410
- // guessing") never matches.
2411
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?Stop\s/,
2412
- name: "Stop opener",
2413
- rule: 'A sentence that opens on the bare command "Stop". It is a listicle hook borrowed wholesale, and it tells the reader what to feel about the advice before giving it. Ramzi, 22 Sep 2026, on a queued Reddit draft: "Stop at the beginning of a sentence is AI slop." Open on the thing itself: "One report per platform is the wrong shape."',
2414
- example:
2415
- '"Stop trying to build one report per platform." / "Stop guessing which query converts."',
2416
- },
2417
- {
2418
- id: "thing-does-it",
2419
- // Sentence-initial "An automation / A script / The checklist" plus a doing verb is narrow on purpose, because product copy says "The app sends" all the time.
2420
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n)(?:#{1,6}[ \t]+)?(?:An?|The)\s+(?:automation|script|workflow|bot|checklist|scenario|macro)\s+(?:creates|makes|sends|assigns|posts|handles|catches|flags|routes|fires|picks|runs|only)\b/,
2421
- name: "Thing as the doer",
2422
- rule: 'A sentence that leads with a tool a person built and gives it the verb, so it reads like a description of a machine with nobody behind it. Ramzi, 30 Sep 2026, on "An automation creates it when a task moves to review and assigns it to someone who isn\'t a founder": Jev scored it 0.73 under `law` and let it through. Put the person first ("We have an automation create it") or make it an instruction ("Have an automation create it").',
2423
- example:
2424
- '"An automation creates it when a task moves to review." / "The script only posts what is approved." / "A checklist catches the rest."',
2425
- },
2426
- {
2427
- id: "unlock-promise",
2428
- name: "Unlock as a promise",
2429
- // A banned word until 15 Oct 2026, when it failed a diagram editor's "Lock or unlock". A lock control takes no object; the promise always has one.
2430
- test: /\bunlock(?:ing)?\s+(?!(?:it|them)\b)[\p{L}\p{N}$€]/iu,
2431
- rule: 'Unlock as the verb of a promise: the reader gets a feeling of access instead of the thing. Say what they can do now: "You see every client\'s margin on one page."',
2432
- example: '"Unlock your team\'s potential" / "unlocking growth"',
2433
- },
2434
- {
2435
- id: "things-that-headline",
2436
- name: "Things that do X",
2437
- // Count-led "N things that X" at a sentence start, or an unpunctuated line opening on a plural noun ("Repos that X"), so "Translate the pages that work" passes.
2438
-
2439
- // After a person noun, French `qui` is "who", so a field label ("Personnes qui doivent se connecter") passes.
2440
- test: /(?:(?:^|[.!?]["'’”)\]]?\s+|\n|:\s+|#+\s+)\d{1,3}\s+(?:[\p{L}\w'’-]+\s+){1,4}(?:that|qui)\s+\p{L}|(?:^|\n|:\s+|#+\s+)(?!(?:People|Users|Members|Personnes|Gens|Utilisateurs|Membres)\s)\p{Lu}[\p{L}'’-]*s\s+(?:[\p{L}'’-]+\s+)?(?:that|qui)\s+[^.!?\n]{3,60}(?=\n|$))/u,
2441
- rule: 'A headline built as "N things that do X": the stock listicle frame, with a vague loss or gain hung on "that". Ramzi, 15 Oct 2026, on "5 agent habits that cost you a review": "XXX that XXX should have been slopped." Name what the reader stops suffering: "5 free repos that fix your coding agent" became "Clean up less after your coding agent".',
2442
- example:
2443
- '"5 agent habits that cost you a review" / "7 ClickUp mistakes that break client work" / "Repos that fix your coding agent"',
2444
- },
2445
- {
2446
- id: "what-is-opener",
2447
- // Sentence-initial "What" heading a cleft ("What X is Y", up to 4 words in X) that closes on a stop rather than a question mark within the same clause,
2448
-
2449
- // so a real question ("What changed?") never matches. Bounded to 100 chars so it cannot reach across a paragraph break and pair an unrelated later "?".
2450
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?[Ww]hat(?:'s|\s+(?:[a-z][\w'’-]*\s+){0,4}?(?:is|was|are|were|works|worked|matters|counts|helped|changed|fixed|killed|caught|survives))\b[^?\n]{0,100}[.!:]/,
2451
- name: "What-is cleft opener",
2452
- rule: 'A sentence that opens "What X is/was Y" instead of just stating Y. The cleft exists to sound considered, and it delays the answer by a clause for nothing. Ramzi, 22 Sep 2026, on the same draft: "\'What\' at the beginning of a sentence that is not a question" is also slop. Say the thing: "A single Programmes list works better," not "What works better is a single Programmes list."',
2453
- example:
2454
- '"What works better is a single Programmes list." / "What\'s actually caught stuff for me is checking the output."',
2455
- },
2456
-
2457
- // --- Next 4: Ramzi, 28 Sep 2026, on the "Editor OS" diagram: "This is AI slop." Every line he
2458
- // pointed at passed this gate with no hit. ---
2459
- {
2460
- id: "not-because-pivot",
2461
- name: "Not because X. Because Y.",
2462
- // `negation-pivot` with the reason swapped in for the thing, but decidable: a sentence opening
2463
- // on "Not because" never opens anything else. The comma form is the same swap.
2464
- test: /(?:^|[.!?]["'’”)\]]?\s+|\n)(?:#{1,6}[ \t]+)?(?:(?:it|that)(?:'s|’s|\s+is|\s+was)\s+)?not\s+because\b[^.!?\n]{2,120}(?:[.!?]\s+|,\s+|\n)(?:(?:it|that)(?:'s|’s|\s+is|\s+was)\s+)?because\b/i,
2465
- rule: "A wrong reason set up so the right one can knock it down. The reader never held the wrong reason, so the first sentence is there for the drama. Give the real reason as a plain sentence.",
2466
- example:
2467
- '"Not because the editing got faster. Because the editing stopped being a decision." / "It\'s not because the tool is slow, it\'s because nobody owns it."',
2468
- },
2469
- {
2470
- id: "comma-then-slogan",
2471
- name: "Do X, then Y",
2472
- // 2 bare verb phrases hung on ", then", no subject, alone on a line, 7 words max: on the UpSys
2473
- // corpus, 28 Sep 2026, every longer hit was UI copy.
2474
- view: "prose",
2475
- test: /^[ \t]*(?=(?:[^\s\n]+[ \t]+){1,6}[^\s\n]+[ \t]*$)[\p{L}][^.!?\n,]{0,40},\s+then\s+[^.!?\n,]{2,40}[.!]?[ \t]*$/imu,
2476
- rule: 'Two orders on one line with a comma and a `then` between them. It reads like a product promise on a box and says nothing about what happens. Say who does what: "You install the layouts once. Every video after that starts at the record button."',
2477
- example:
2478
- '"Set up once, then press record" / "Record, then hand it over" / "Brief it once, then walk away."',
2479
- },
2480
- {
2481
- id: "in-out-pair",
2482
- name: "X goes in. Y comes out.",
2483
- test: /\b(?:goes|go|went|comes|come|came)\s+in\b[^.!?\n]{0,20}[.!?]\s+[^.!?\n]{2,60}\b(?:comes|come|came|goes|go|went)\s+out\b/i,
2484
- rule: "A machine drawn as a pipe with two ends. It skips everything the reader wanted to know, which is what happens in the middle. Name the steps, or the one step that matters.",
2485
- example:
2486
- '"A raw take goes in. A cut, dressed video comes out." / "Your notes go in. A finished deck comes out."',
2487
- },
2488
- {
2489
- id: "zero-tail",
2490
- name: "X, zero Y",
2491
- // Verbless: noun phrase, comma, `zero` and a noun phrase, or "No X, no Y". A bare `, no` tail
2492
- // only hit status labels ("Parked, no slot yet"), 28 Sep.
2493
- view: "prose",
2494
- test: /^[ \t]*(?:[^.!?\n,]{3,40},\s+zero|no\s+[^.!?\n,]{2,40},\s+no)\s+[\p{L}][^.!?\n,]{1,30}[.!]?[ \t]*$/imu,
2495
- rule: "A thing and a missing thing, joined by a comma, with no verb. It's a tagline, and the tag is always a cost the reader never mentioned. Write the sentence: \"The edit took under an hour and I didn't choose a single layout.\"",
2496
- example:
2497
- '"An hour of editing, zero decisions" / "No brand, no named pieces" / "Two clicks, zero setup"',
2498
- },
2499
- // The next 3 are Ramzi's, 2 Oct 2026, on a CutKit script about spotting AI slop that scored 94 and passed this gate with zero findings.
2500
- {
2501
- id: "once-twice-law",
2502
- name: "Once is craft. Twice is a tell.",
2503
- test: /\b(?:once|one\s+time|a\s+single\s+time)\s+(?:is|=)\s+(?:an?\s+)?[\w-]+(?:\s+[\w-]+)?[.,;]\s*(?:twice|two\s+times|again)\s+(?:is|=)\s+(?:an?\s+)?[\w-]+|\b(?:appears?|happens?|shows?\s+up)\s+once\s+(?:is|are)\s+[^.!?]{2,25},?\s+(?:while|but|and)\s+[^.!?]{2,40}\b(?:repeats?|twice|again)\b[^.!?]{0,20}\b(?:is|are)\b/i,
2504
- rule: 'A two-beat law: "once is X, twice is Y". It sounds like a rule and is a slogan, because the reader can\'t check it and it stands in for the sentence that would say what to look for. Say the thing: what repeats, how often, and what you do about it.',
2505
- example:
2506
- '"Once is craft. Twice is a tell." / "A shape that appears once is craft, while a shape that repeats is a tell"',
2507
- },
2508
- {
2509
- id: "while-antithesis",
2510
- name: "Real writing jumps, while raw AI stays flat",
2511
- view: "prose",
2512
- test: /[^.!?\n]{8,80},\s+while\s+(?:a|an|the|raw|real|good|bad|plain|your)\s+[^.!?\n,]{2,60}\s+(?:is|are|stays?|runs?|ships?|sits?|reads?|hides?|repeats?)\b/i,
2513
- rule: 'A comma, "while", and the mirror clause. The sentence exists to set two things side by side, and the contrast does the work a fact should. One per script is a style. Several is the shape of a model. Split it into two sentences and give each its own evidence, or drop the half that only mirrors the other.',
2514
- example:
2515
- '"Real writing jumps from 3 words to 40, while raw AI stays flat." / "Accuse a good writer and you lose them, while the real slop ships."',
2516
- },
2517
- {
2518
- id: "youd-think-setup",
2519
- name: "You'd think finding one word is proof",
2520
- test: /\byou(?:'|’)?d\s+(?:think|assume|expect)\b|\byou\s+(?:might|may|would)\s+(?:think|assume|expect)\b/i,
2521
- rule: 'A strawman handed to the reader so the next clause can correct it: "you\'d think X, but Y". It sets a belief up only to knock it over and attributes it to the viewer. State what is true, then the evidence. When a real belief needs breaking, name who holds it ("most agencies check for...").',
2522
- example:
2523
- '"You\'d think finding one word is proof, but a shape that appears once is craft." / "You might think it needs a rewrite"',
2524
- },
2525
- ];
2526
-
2527
- /**
2528
- * Machine residue. The citation and formatting markup a chatbot leaks into its own output, one entry per tool that leaks it.
2529
- */
2530
-
2531
- /*
2532
- * WHY this is separate from `patterns`: a pattern is a judgement about a sentence and a person can disagree with it. These are certainties.
2533
- */
2534
-
2535
- /*
2536
- * No writer types `:contentReference[oaicite:0]`, `【85†L261-269】` or `utm_source=chatgpt.com` into finished copy, so a hit is not a style opinion, it is the receipt.
2537
- */
2538
-
2539
- /*
2540
- * Wikipedia:Signs of AI writing calls it "an unambiguous indicator that the text originated with AI" (WP:OAICITE, WP:STARTSPAN, WP:GROKCARD), and it is the only half of that page that needs no
2541
- */
2542
-
2543
- /*
2544
- * corpus check before shipping.
2545
- */
2546
-
2547
- /*
2548
- * Language neutral by construction: the residue is the same in every language, which is why the French page lists `:contentReference[oaicite:2]{index=2}` under "Sources rédigées avec une syntaxe inconnue".
2549
- */
2550
- export const artifacts = [
2551
- {
2552
- id: "openai-citation",
2553
- name: "ChatGPT citation residue",
2554
- test: /:contentReference\[oaicite:\d+\]|\boai_citation\b|\bcontentReference\b|\bcite\u{E200}?turn\d+|\bturn\d+(?:search|image|news|file|view|forecast)\d+|\{"attribution":\s*\{"attributableIndex"/u,
2555
- rule: "ChatGPT's internal reference markup, pasted through. Delete it and write the citation, or delete the sentence that needed one.",
2556
- example: '":contentReference[oaicite:0]{index=0}" / "citeturn0search3"',
2557
- },
2558
- {
2559
- id: "gemini-citation",
2560
- name: "Gemini citation residue",
2561
- test: /\[cite:\s*[\d,\s]+\]|\[span_\d+\]\((?:start|end)_span\)|\((?:start|end)_span\)/,
2562
- rule: "Gemini's citation and span markup, pasted through. Delete it.",
2563
- example: '"[cite: 3, 12, 13]" / "[span_1](start_span)"',
2564
- },
2565
- {
2566
- id: "grok-citation",
2567
- name: "Grok citation residue",
2568
- test: /grok_render_citation_card_json|<\/?grok-card\b|\bgrok_card\b|[?&]referrer=grok\.com\b/i,
2569
- rule: "Grok's citation card markup, pasted through. Delete it.",
2570
- example: '"<grok-card data-id=...>" / "grok_render_citation_card_json"',
2571
- },
2572
- {
2573
- id: "deepseek-citation",
2574
- name: "DeepSeek citation residue",
2575
- test: /【\d+†[^】]*】/,
2576
- rule: "DeepSeek's lenticular-bracket footnote markup, pasted through. Delete it.",
2577
- example: '"【85†L261-269】"',
2578
- },
2579
- {
2580
- id: "perplexity-citation",
2581
- name: "Perplexity citation residue",
2582
- test: /\[(?:attached_file|web):\d+\]|ppl-ai-file-upload/i,
2583
- rule: "Perplexity's file and web reference markup, pasted through. Delete it.",
2584
- example: '"[attached_file:1]" / "[web:1]"',
2585
- },
2586
- {
2587
- id: "assistant-utm",
2588
- name: "Assistant UTM tag",
2589
- // The link the model handed back, with its own referral tag still on it. It
2590
- // proves the URL came from a chatbot even when a human wrote the sentence.
2591
- test: /[?&](?:utm_source=(?:chatgpt\.com|openai|copilot\.com|perplexity\.ai)|referrer=grok\.com)\b/i,
2592
- rule: "A URL still carrying the chatbot's referral parameter. Strip the query string back to the link the reader needs.",
2593
- example: '"https://example.com/article?utm_source=chatgpt.com"',
2594
- },
2595
- {
2596
- id: "document-block-markup",
2597
- name: "Document block markup",
2598
- // The `:::writing{variant="document" id=...}` wrapper, and the fenced
2599
- // wikitext block a chatbot emits when asked for markup it does not speak.
2600
- test: /:::\s*writing\{|```\s*wikitext\b|↩️?/,
2601
- rule: "A document wrapper or a footnote return arrow the chat interface added around the answer. Delete the wrapper and keep the text.",
2602
- example: ':::writing{variant="document" id="12345"} / "```wikitext"',
2603
- },
2604
- {
2605
- id: "assistant-turn-markup",
2606
- name: "Assistant turn markup",
2607
- // A model's own control tags. `function_calls` and `thinking` reach copy
2608
- // when a transcript is pasted rather than the answer.
2609
- test: /<\/?(?:thinking|antml:[a-z_]+|function_calls|invoke name=)\b/i,
2610
- rule: "A control tag from the model's own turn, pasted with the answer. Delete it, and check what else came with it.",
2611
- example: '"<thinking>" / "<function_calls>"',
2612
- },
2613
- ];
2614
-
2615
- /**
2616
- * Checked on titles and headings only: a comma there is cadence standing in for
2617
- * a subject. A colon that labels the subject is fine. Home of `course-lint`'s rule.
2618
- */
2619
- export const titleTells = [
2620
- { id: "title-comma", test: /,/, rule: "comma in a title (one clause, no second beat)" },
2621
- { id: "title-not-y", test: /,\s+not\s+/i, rule: '"X, not Y" antithesis' },
2622
- ];
64
+ export const shapes = [...shapesReveals, ...shapesFraming, ...shapesDensity];
2623
65
 
2624
66
  /**
2625
67
  * The one prompt block every AI caller should use. Renders the same bans from the same data, so a prompt cannot drift from the linter.