@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
@@ -0,0 +1,102 @@
1
+ import { COUNT, DURATION, TAIL_WORD, SENTENCE_OPEN } from "#lint/data/slop/pattern-parts.js";
2
+
3
+ /** Patterns for a duration with no verb and for stop, unlock and cleft openers. */
4
+ export const patternsDurationAndOpeners = [
5
+ // --- 18 Sep 2026.
6
+
7
+ // 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
8
+
9
+ // are the same token to a regex ("sound on" against "turn the sound on").
10
+
11
+ // A duration is the sub-case where the token cannot be a verb, so the missing predicate is decidable.
12
+ {
13
+ id: "bare-duration-clause",
14
+ name: "N minutes, no verb",
15
+ /**
16
+ * A count, a time unit, a comma, and no verb on either side of it.
17
+ */
18
+
19
+ /*
20
+ * A duration noun is never an imperative, so the head has no predicate by construction.
21
+ */
22
+
23
+ /*
24
+ * 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,
25
+ */
26
+
27
+ /*
28
+ * and a real second clause carries a subject and a finite verb, both of which `TAIL_WORD` forbids.
29
+ */
30
+
31
+ /*
32
+ * 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,
33
+ */
34
+
35
+ /*
36
+ * because "3 years, 2 months" and "Four days, five" are lists; and the clause has to close on a stop rather than a newline,
37
+ */
38
+
39
+ /*
40
+ * 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.
41
+ */
42
+ test: new RegExp(
43
+ `${SENTENCE_OPEN}\\**${COUNT}[ \\t]+${DURATION}\\**[ \\t]*,[ \\t]+` +
44
+ `(?!(?:and|or|but|so|then|which|that|who|because|if|while|until)[ \\t])` +
45
+ `(?!(?:\\d|${COUNT})(?![\\w'’-]))` +
46
+ `(?:${TAIL_WORD}[ \\t]+){0,2}${TAIL_WORD}\\**[ \\t]*(?=[.!?]|[ \\t]*$)`,
47
+ "i",
48
+ ),
49
+ 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".',
50
+ example: '"2 minutes, sound on." / "Three days, tops." / "20 minutes, no slides."',
51
+ },
52
+ {
53
+ id: "stop-opener",
54
+ // Sentence-initial "Stop", bare, no "start"/"begin" pairing (that shape is
55
+ // `stop-start`). Case-sensitive so mid-sentence "stop" ("when you stop
56
+ // guessing") never matches.
57
+ test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?Stop\s/,
58
+ name: "Stop opener",
59
+ 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."',
60
+ example:
61
+ '"Stop trying to build one report per platform." / "Stop guessing which query converts."',
62
+ },
63
+ {
64
+ id: "thing-does-it",
65
+ // 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.
66
+ 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/,
67
+ name: "Thing as the doer",
68
+ 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").',
69
+ example:
70
+ '"An automation creates it when a task moves to review." / "The script only posts what is approved." / "A checklist catches the rest."',
71
+ },
72
+ {
73
+ id: "unlock-promise",
74
+ name: "Unlock as a promise",
75
+ // 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.
76
+ test: /\bunlock(?:ing)?\s+(?!(?:it|them)\b)[\p{L}\p{N}$€]/iu,
77
+ 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."',
78
+ example: '"Unlock your team\'s potential" / "unlocking growth"',
79
+ },
80
+ {
81
+ id: "things-that-headline",
82
+ name: "Things that do X",
83
+ // 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.
84
+
85
+ // After a person noun, French `qui` is "who", so a field label ("Personnes qui doivent se connecter") passes.
86
+ 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,
87
+ 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".',
88
+ example:
89
+ '"5 agent habits that cost you a review" / "7 ClickUp mistakes that break client work" / "Repos that fix your coding agent"',
90
+ },
91
+ {
92
+ id: "what-is-opener",
93
+ // 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,
94
+
95
+ // 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 "?".
96
+ 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}[.!:]/,
97
+ name: "What-is cleft opener",
98
+ 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."',
99
+ example:
100
+ '"What works better is a single Programmes list." / "What\'s actually caught stuff for me is checking the output."',
101
+ },
102
+ ];
@@ -0,0 +1,116 @@
1
+ import { SENTENCE_OPEN } from "#lint/data/slop/pattern-parts.js";
2
+
3
+ /** Patterns for question and placeholder headings, definitional leads and hypothetical laws. */
4
+ export const patternsHeadingsAndLaws = [
5
+ {
6
+ id: "question-heading",
7
+ name: "Question as a heading",
8
+ // The fr page's "titres de sections sous forme de question".
9
+
10
+ // 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,
11
+
12
+ // not in the outline.
13
+ view: "faqless",
14
+ test: /^#{1,6}\s+[^\n?]{5,90}\?\s*$/m,
15
+ 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.",
16
+ example: '"## Why does this matter?" / "## Qu\'est-ce que le pilotage ?"',
17
+ },
18
+ {
19
+ id: "inline-header-list",
20
+ name: "Inline-header vertical list",
21
+ // 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.
22
+
23
+ // The colon is required: a list of bold link labels with no colon is ordinary markdown.
24
+ test: /^[ \t]*(?:[-*+•–—]|\d+[.)])\s+\*\*[^*\n]{2,60}(?:[::]\*\*|\*\*\s*[::])/m,
25
+ 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.",
26
+ example:
27
+ '"- **Route Details**: Starts at Medak and ends at Bhainsa." / "1. **Recommended:** use the shorter form."',
28
+ },
29
+ {
30
+ id: "placeholder-text",
31
+ name: "Unfilled placeholder",
32
+ // WP:AIPLACEHOLDER. A bracketed fill-in-the-blank, a parenthesised instruction to the writer, or a date field the model could not resolve.
33
+
34
+ // `x` and `y` are deliberately not accepted as bracket words, because `- [x]` is a task list.
35
+
36
+ // 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.
37
+ 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,
38
+ 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.",
39
+ example: '"[Entertainer\'s Name]" / "(Add your channel URL here)" / "access-date=2025-xx-xx"',
40
+ },
41
+ {
42
+ id: "definitional-lead",
43
+ name: "Title as a proper noun",
44
+ // A lead sentence that defines its own headline instead of the thing.
45
+
46
+ // The anchor is a line start plus a capital, so an ordinary mid-paragraph "the term refers to a shorthand" does not match.
47
+
48
+ // The second branch is the list article that reads its own title as a noun, which "Paris is a city" is not,
49
+
50
+ // so the branch starts at "List of" and nowhere else.
51
+ 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,
52
+ 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 ...".',
53
+ example:
54
+ '"Catchment area (health) refers to the geographic area from which ..." / "List of songs about Mexico is a curated compilation ..."',
55
+ },
56
+ {
57
+ id: "sentence-not-pivot",
58
+ name: "Sentence pivot",
59
+ // The full-stop form of `negation-pivot`, which `comma-not-pivot` cannot see.
60
+
61
+ // 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.
62
+
63
+ // 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.
64
+ test: /(?:^|[.!?]\s+)(?:No|Nothing|Nobody)\s+[^.!?\n]{2,70}[.!?]\s+(?:It|That|This)(?:'s|’s|\s+is)\s+(?!not\b)/u,
65
+ rule: "A denial standing in for a statement, split across two sentences. State what the thing is and let the contrast be implied.",
66
+ example:
67
+ '"No video generator made this. It is code." / "Nothing was automated here. That is the point." / "Nobody wrote the copy. It is a template."',
68
+ },
69
+ {
70
+ id: "elliptical-flip",
71
+ name: "This one doesn't",
72
+ // Ramzi, 23 Sep 2026. 3 hits across all first-party copy, 0 in his transcripts.
73
+ test: new RegExp(
74
+ `${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)[.!]`,
75
+ "u",
76
+ ),
77
+ 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."',
78
+ example:
79
+ '"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."',
80
+ },
81
+ {
82
+ id: "watching-metadiscourse",
83
+ name: "Telling the reader what they are doing",
84
+ // Interpretive metadiscourse aimed at the artefact in front of the reader.
85
+
86
+ // 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
87
+
88
+ // act of looking at it.
89
+ test: /\byou(?:'re|’re|\s+are)\s+(?:watching|looking\s+at|seeing|reading)\s+(?:the|a|an|this|that|my|our)\b/i,
90
+ rule: "A line that narrates the reader's own act of looking instead of saying the thing. Cut the frame and keep the fact.",
91
+ example:
92
+ '"You are watching the second attempt." / "You\'re looking at the rebuild." / "You are reading the third draft."',
93
+ },
94
+ {
95
+ id: "once-you-law",
96
+ name: "Hypothetical law",
97
+ // The advisory aside dressed as a rule of nature: a condition the writer invented, then a consequence the reader is told they will feel.
98
+
99
+ // Anchored on "Once you" plus a second-person consequence verb, so an ordinary "Once you have the invoice, send it" does not match.
100
+ 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,
101
+ rule: "A law about what the reader will feel, invented one clause earlier. Say the fact and let the reader draw the consequence.",
102
+ example:
103
+ '"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."',
104
+ },
105
+ {
106
+ id: "the-x-that-y-headline",
107
+ name: "The X that Y",
108
+ // 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:
109
+
110
+ // a title or a card label sits alone on its line, and this only fires when that entire line is the construction.
111
+ 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,
112
+ 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."',
113
+ example:
114
+ '"The fifth ask that cost me nothing" / "The favor that stopped eating my week" / "The handover that leaves no loose thread"',
115
+ },
116
+ ];
@@ -0,0 +1,94 @@
1
+ /** Patterns for spelled-out numbers, numbered labels and comma-run lists. */
2
+ export const patternsNumbersAndRuns = [
3
+ {
4
+ id: "spelled-out-quantity",
5
+ name: "Spelled-out quantity",
6
+ // 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.
7
+
8
+ // `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
9
+
10
+ // still covers it for the human read.
11
+
12
+ // 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,
13
+
14
+ // so "17 million last year" failed the gate it passes by construction. Caught auditing the 45 planned posts.
15
+
16
+ // 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.
17
+
18
+ // It fired 8 times across the UpSys blog, in both languages.
19
+
20
+ // `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.
21
+
22
+ // `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.
23
+
24
+ // The singular is always an adjective, and `\b` keeps "two ways" caught, which is a real quantity.
25
+
26
+ // A relative pronoun or `of` after the cardinal means it counts no noun ("the one or two that carry weight"), 15 Oct 2026.
27
+ 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,
28
+ 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.",
29
+ example:
30
+ '"forty pages" / "nineteen minutes beat twenty-nine" / "twenty per cent of the pipeline"',
31
+ },
32
+ {
33
+ id: "spelled-out-label",
34
+ name: "Numbered label in words",
35
+ // 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,
36
+
37
+ // so "Lesson two:" never reaches that test. The noun list is closed and every entry is an index into a set the writer made.
38
+
39
+ // `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.
40
+ 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,
41
+ 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.",
42
+ example: '"Lesson one: stop selling the tool" / "Step three" / "Part two of the build"',
43
+ },
44
+ {
45
+ id: "ring-label",
46
+ name: "Ring as a numbered label",
47
+ // 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.
48
+
49
+ // A number is allowed to follow the real noun (Load 2, Step 3), never the shape it was drawn as.
50
+
51
+ // Restricted to a following number so "ring the bell" and a phone ringing stay ordinary English.
52
+ test: /(?:^|[.!?]["'’”)\]]?\s+|\n)\s*(?:#{1,6}[ \t]+)?(?:[-*•]\s*)?ring\s+(?:\d+|one|two|three|four|five|six|seven|eight|nine|ten)\b/i,
53
+ 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.",
54
+ example: '"RING 2" / "Ring one: your business" / "Ring 4, the schedule"',
55
+ },
56
+ {
57
+ id: "comma-run",
58
+ name: "Comma-run list",
59
+ // 3+ fragments strung on commas with no conjunction anywhere, all short.
60
+
61
+ // 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,
62
+
63
+ // or it is 2 items, or it is bullets.
64
+ view: "prose",
65
+ 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,
66
+ 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.",
67
+ example:
68
+ '"One connector, read the permission screen, 12 slides back." / "Fast, cheap, reliable." / "The brief, the offer, the tone."',
69
+ },
70
+ {
71
+ id: "nobody-opener",
72
+ name: "Nobody opener",
73
+ // Sentence-initial only. Mid-sentence "and nobody reads it" is an ordinary
74
+ // clause; the tell is the crowd taking the first position, where the
75
+ // reader's own problem belongs.
76
+ test: /(?:^|[.!?]["'’”)\]]?\s+|\n)\s*(?:#{1,6}[ \t]+)?(?:nobody|no one|no-one)\s+[a-zà-ÿ]/i,
77
+ 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.",
78
+ example:
79
+ '"Nobody wakes up wanting an app." / "No one reads the second page." / "Nobody has time for this."',
80
+ },
81
+ {
82
+ id: "reassurance-relative",
83
+ name: "Reassurance relative clause",
84
+ // The verb set is deliberately short: comprehension and ease only.
85
+
86
+ // "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
87
+
88
+ // bad.
89
+ 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,
90
+ 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.",
91
+ example:
92
+ '"A monthly report you can read" / "a dashboard you can actually use" / "a process that makes sense" / "a tool that just works"',
93
+ },
94
+ ];
@@ -0,0 +1,90 @@
1
+ import { PARTICIPLE_LIST } from "#lint/data/slop/pattern-parts.js";
2
+
3
+ /** Patterns for sentence openers and the benefit tails hung on the end. */
4
+ export const patternsOpenersAndTails = [
5
+ // 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.
6
+ {
7
+ id: "and-escalation",
8
+ name: "And most of them are",
9
+ 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,
10
+ 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.',
11
+ example:
12
+ '"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."',
13
+ },
14
+ {
15
+ id: "which-is-why",
16
+ name: "Which is exactly why",
17
+ test: /, which is (?:exactly |precisely )?(?:why|what|how)\b/i,
18
+ rule: "A tidy causal tail that closes the loop for the viewer. Say the cause as its own sentence, or let them reach it.",
19
+ example:
20
+ '"The service still making you money is the one keeping you stuck, which is exactly why you haven\'t touched it."',
21
+ },
22
+ {
23
+ id: "labelled-turn",
24
+ name: "The awkward part is that",
25
+ test: /\bthe (?:awkward|uncomfortable|hard|tricky|funny|scary|annoying|ugly|brutal|interesting|surprising|real) (?:part|bit|thing|truth)(?: here)? is that\b/i,
26
+ rule: "A label announcing that the next sentence matters. Delete the label and start on the fact.",
27
+ example:
28
+ '"The awkward part is that this list keeps rotting." / "The uncomfortable bit is that the branch you cut is still alive."',
29
+ },
30
+ {
31
+ id: "there-is-only",
32
+ name: "There's no X. There's only Y.",
33
+ test: /\bthere'?s no [^.!?]+[.!?]\s+there'?s only\b/i,
34
+ rule: "A negation pivot split over 2 sentences to sound final. State the Y.",
35
+ example: "\"There's no detector for this. There's only a list.\"",
36
+ },
37
+ {
38
+ id: "nobody-ever",
39
+ name: "Nobody has ever",
40
+ test: /\b(?:nobody|no one|no-one) (?:has |had )?ever\b/i,
41
+ rule: 'An absolute nobody measured. Say what you saw, with its count: "none of the 12 people I onboarded learned it from the doc."',
42
+ example: '"Nobody has ever learned a process from a paragraph."',
43
+ },
44
+ {
45
+ id: "is-where-people",
46
+ name: "Is where people stop",
47
+ test: /\bis where (?:people|you|most|everyone|teams?|clients?|readers?) (?:stop|quit|leave|give up|lose|drop)\b/i,
48
+ rule: 'A place standing in for a behaviour. Say what people do and when: "people stop reading after the first paragraph."',
49
+ example: '"A wall of paragraphs is where people stop reading."',
50
+ },
51
+ {
52
+ id: "every-opener",
53
+ // Case-sensitive so the lookahead spares Sitehub's plan names, which are proper nouns.
54
+ test: /(?:^|[.!?]["'’”)\]]?\s+|\n|["'`])\s*(?:#{1,6}[ \t]+)?(?:EVERY|[Ee]very|EACH|Each)\s(?!(?:Town|Search|Service|other|of)\b)/,
55
+ name: "Every or Each opener",
56
+ 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."',
57
+ example:
58
+ '"Every number names its source article." / "Each workflow arrives named, grouped and explained."',
59
+ },
60
+ {
61
+ id: "participle-stack",
62
+ name: "Named, grouped and explained",
63
+ // 3 past participles in one list, tags allowed between. 0 hits on 190 of his posts, 3 on the website.
64
+ test: new RegExp(
65
+ `\\b${PARTICIPLE_LIST},\\s+(?:<[^>]+>\\s*)?${PARTICIPLE_LIST},?\\s+(?:and|or)\\s+${PARTICIPLE_LIST}\\b`,
66
+ ),
67
+ 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."',
68
+ example:
69
+ '"Each workflow arrives named, grouped and explained." / "each one built, tested and documented"',
70
+ },
71
+ {
72
+ id: "participle-opener",
73
+ // Put, Cut, Set, Read and Run open imperatives as often as participles, so they're out.
74
+ // "Done when" names a step's finish line, the house shape since 4 Oct 2026.
75
+ 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/,
76
+ name: "Participle opener",
77
+ 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.",
78
+ example:
79
+ '"Built in your own colours" / "Found when your town searches" / "Named when somebody asks ChatGPT"',
80
+ },
81
+ {
82
+ id: "reader-benefit-tail",
83
+ // A conjunction or wh-word before `you` makes it a real clause (so your team can rest), not this.
84
+ 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,
85
+ name: "Reader-benefit tail",
86
+ 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.",
87
+ example:
88
+ '"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."',
89
+ },
90
+ ];
@@ -0,0 +1,100 @@
1
+ import { SUBJECT_STOP, PARTICIPLE, NOUN_PHRASE_STOP, INTRANSITIVE_PAST, PREPOSITION, FINITE_AUXILIARY, CLAUSE_SUBJECT, PRESENT_VERB, OBJECT_DETERMINER } from "#lint/data/slop/pattern-parts.js";
2
+
3
+ /** Patterns for parallel, paired and countdown sentence shapes. */
4
+ export const patternsParallelShapes = [
5
+ {
6
+ id: "before-it-happens-countdown",
7
+ name: "Before it happens again",
8
+ // A closing imperative racing a recurrence: "before it happens again" or "before it happens a 4th time".
9
+
10
+ // The ordinal or "again" is required, so an ordinary "finish it before it happens" (a real deadline, no recurrence) does not match.
11
+ test: /\bbefore\s+it\s+happens\s+(?:again|(?:a\s+)?(?:\d+(?:st|nd|rd|th)|another)(?:\s+time)?)\b/i,
12
+ 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."',
13
+ example:
14
+ '"Write each one down before it happens a 4th time." / "Fix the root cause before it happens again."',
15
+ },
16
+ {
17
+ id: "universal-so-payoff",
18
+ name: "Every X, so Y",
19
+ // A universal quantifier ("Every"/"All") stating a generalization, then a
20
+ // comma-"so" clause delivering a tidy payoff. Bounded to one sentence so
21
+ // it cannot cross a paragraph and pair two unrelated claims.
22
+ test: /\b(?:Every|All)\s+[^.!?\n]{3,60},\s+so\s+[^.!?\n]{3,60}[.!?]/i,
23
+ 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.',
24
+ example:
25
+ '"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."',
26
+ },
27
+ {
28
+ id: "how-adj-subject-verb-final",
29
+ name: "How busy the day is",
30
+ // "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,
31
+
32
+ // 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.
33
+ 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,
34
+ 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.',
35
+ example:
36
+ '"no matter how busy the day is" / "no matter how tight the deadline was" / "no matter how loud the room gets"',
37
+ },
38
+ {
39
+ id: "paired-copula",
40
+ name: "X is the A, Y is the B",
41
+ // Two "is the" clauses on ONE line, the second riding on the first.
42
+
43
+ // 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:
44
+
45
+ // "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.
46
+ 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,
47
+ 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.",
48
+ example:
49
+ '"News is the signal. The dataset is the answer." / "The diff is the product, the version is the receipt."',
50
+ },
51
+ {
52
+ id: "elided-passive",
53
+ name: "X built for Y",
54
+ // 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.
55
+ test: new RegExp(
56
+ `(?:^|["'\`]|#{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])))`,
57
+ "m",
58
+ ),
59
+ 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."',
60
+ example:
61
+ '"ClickUp rebuilt around your cases" / "Scenarios built on your own stack" / "4 hours saved on each"',
62
+ },
63
+ {
64
+ id: "parallel-clauses",
65
+ name: "X does the A, Y does the B",
66
+ // Isocolon: two clauses cut to one build (subject, present verb, object) side by side. Widens `paired-copula` past "is the".
67
+ test: new RegExp(
68
+ `(?:^|[.!?:]["'’”)]?[ \\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`,
69
+ "m",
70
+ ),
71
+ 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.',
72
+ example:
73
+ '"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."',
74
+ },
75
+ {
76
+ id: "for-any-tail",
77
+ name: "..., for any X",
78
+ // A question or an inquisitive imperative, then a comma and a universal scope bolted on as a closer.
79
+
80
+ // The opener set is closed and the tail is `for` plus a quantifier, so "it is priced in euros, for each importer" (no opener),
81
+
82
+ // "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.
83
+ 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,
84
+ 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.",
85
+ example:
86
+ '"Know what CBAM costs you, for any CN code." / "What CBAM costs you, for one CN code."',
87
+ },
88
+ {
89
+ id: "before-you-verb-it",
90
+ name: "X before you Y it",
91
+ // A whole line that is a noun, then a second-person clause telling the reader when they are allowed to act.
92
+
93
+ // 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:
94
+
95
+ // this only fires on the heading shape.
96
+ 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,
97
+ 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.",
98
+ example: '"Questions before you use it" / "What to check before you ship it"',
99
+ },
100
+ ];
@@ -0,0 +1,101 @@
1
+ /** Patterns for flat reveals, stock pivots and counted claims. */
2
+ export const patternsRevealsAndTallies = [
3
+ {
4
+ id: "tool-does-the-job",
5
+ name: "13 skills do the writing",
6
+ 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,
7
+ 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."',
8
+ example:
9
+ '"13 public skills do the writing, the meta fields and the reads" / "the agent does the research"',
10
+ },
11
+ {
12
+ id: "free-as-figure",
13
+ name: "The moment capture is free",
14
+ 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,
15
+ 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.',
16
+ example:
17
+ '"The moment capture is free" / "One moment in every process costs nothing to capture"',
18
+ },
19
+ {
20
+ id: "ends-on-verb",
21
+ name: "A page the market asked for",
22
+ 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,
23
+ 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.',
24
+ example:
25
+ '"Impressions with no page behind them is a page the market asked for" / "Capture the answer when it\'s first said"',
26
+ },
27
+ {
28
+ id: "count-of-total",
29
+ name: "62 of 99 agency owners",
30
+ 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,
31
+ 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."',
32
+ example:
33
+ '"62 of 99 agency owners describe work going missing" / "73 of the 99 agencies I have worked with"',
34
+ },
35
+ {
36
+ id: "paired-backref",
37
+ name: "The first X, and the second Y in it",
38
+ 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,
39
+ 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.',
40
+ example:
41
+ '"The first builds the workspace, and the week runs inside it on the second." / "The first course sets it up. The second runs it."',
42
+ },
43
+ {
44
+ id: "you-injunctive",
45
+ name: "You put, you add",
46
+ 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/,
47
+ 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".',
48
+ example: '"You keep all the numbers in 1 file" / "You end each lesson with something built"',
49
+ },
50
+ {
51
+ id: "you-now-know",
52
+ name: "You now know",
53
+ test: /\bYou now know\b/,
54
+ 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."',
55
+ example: '"You now know the loop and why each step is there."',
56
+ },
57
+ // 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.
58
+ {
59
+ id: "stock-half-pivot",
60
+ name: "The easy half",
61
+ test: /\b(?:easy|easier|hard|harder|simple|tricky) half\b/i,
62
+ 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."',
63
+ example: '"Deleting is the easy half." / "The counting is the easy half."',
64
+ },
65
+ {
66
+ id: "because-parallel",
67
+ name: "Same verb, because, twice",
68
+ test: /\b(\w+), because\b[^.!?]*[.!?]["'”’]?\s+[^.!?]*?\b\1, because\b/i,
69
+ 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."',
70
+ example:
71
+ '"The old line goes, because it always thinks. The next one goes, because it already is."',
72
+ },
73
+ {
74
+ id: "called-splice",
75
+ name: "It's called X, and",
76
+ test: /, (?:it'?s|it is|this is|that'?s) called [^,.;]{1,60}, and\b/i,
77
+ 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."',
78
+ example: '"Anthropic shipped the fix, it\'s called prompt-audit, and it reads your files."',
79
+ },
80
+ {
81
+ id: "shipped-the-fix",
82
+ name: "Shipped the fix",
83
+ test: /\b(?:shipped|released|built|put out|dropped|rolled out) (?:the|a) fix\b/i,
84
+ rule: 'Launch-announcement voice. "The fix" presumes a problem the viewer never agreed to. Name the thing and show it running.',
85
+ example: '"Anthropic shipped the fix inside Claude Code."',
86
+ },
87
+ {
88
+ id: "never-meant",
89
+ name: "Places you never meant",
90
+ test: /\b(?:places|ways|things|spots) you never (?:meant|intended|expected|wanted)\b/i,
91
+ rule: "A vague consequence standing in for a real one. Name the place: which task, which output, what went wrong.",
92
+ example: '"A rule in capitals gets applied in places you never meant it to go."',
93
+ },
94
+ {
95
+ id: "made-sense-ago",
96
+ name: "Made sense a year ago",
97
+ test: /\bmade (?:perfect |total )?sense (?:back then|(?:a|one|two|three|\d+) (?:year|month|week)s? ago)\b/i,
98
+ rule: "A backstory with a date nobody measured. Either give the real date and source, or cut the history and state the current fact.",
99
+ example: '"All the MUSTs in there made sense a year ago."',
100
+ },
101
+ ];