@heyramzi/lint 1.34.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 (60) hide show
  1. package/README.md +52 -5
  2. package/bin/heyramzi-comment-length.js +5 -6
  3. package/bin/heyramzi-file-tokens.js +2 -2
  4. package/bin/heyramzi-old-names.js +72 -0
  5. package/bin/heyramzi-push-diff.js +16 -5
  6. package/bin/heyramzi-slop.js +3 -1
  7. package/bin/heyramzi-ui-rules.js +18 -9
  8. package/comment-length.js +18 -12
  9. package/config/oxlintrc.json +3 -4
  10. package/data/jev-code-bench.js +5 -5
  11. package/data/slop/artifacts.js +87 -0
  12. package/data/slop/pattern-parts.js +56 -0
  13. package/data/slop/patterns/appositives-and-sayings.js +81 -0
  14. package/data/slop/patterns/comma-clauses.js +106 -0
  15. package/data/slop/patterns/diagram-and-script-tells.js +71 -0
  16. package/data/slop/patterns/dropped-elements.js +149 -0
  17. package/data/slop/patterns/duration-and-openers.js +102 -0
  18. package/data/slop/patterns/headings-and-laws.js +116 -0
  19. package/data/slop/patterns/numbers-and-runs.js +94 -0
  20. package/data/slop/patterns/openers-and-tails.js +90 -0
  21. package/data/slop/patterns/parallel-shapes.js +100 -0
  22. package/data/slop/patterns/reveals-and-tallies.js +101 -0
  23. package/data/slop/patterns/setups-and-closers.js +83 -0
  24. package/data/slop/patterns/subject-voice.js +67 -0
  25. package/data/slop/patterns/vague-and-flourish.js +102 -0
  26. package/data/slop/patterns/wikipedia-signs.js +103 -0
  27. package/data/slop/patterns.js +62 -0
  28. package/data/slop/phrases-en-closers.js +66 -0
  29. package/data/slop/phrases-en-core.js +185 -0
  30. package/data/slop/phrases-en-wikipedia.js +136 -0
  31. package/data/slop/phrases-fr.js +152 -0
  32. package/data/slop/shapes-density.js +81 -0
  33. package/data/slop/shapes-framing.js +101 -0
  34. package/data/slop/shapes-reveals.js +88 -0
  35. package/data/slop/title-tells.js +8 -0
  36. package/data/slop/words-en.js +178 -0
  37. package/data/slop/words-fr.js +101 -0
  38. package/data/slop-words.js +18 -2576
  39. package/data/vendor/heading-words.js +6 -0
  40. package/file-tokens.js +26 -13
  41. package/index.js +4 -6
  42. package/inline-path.js +2 -0
  43. package/jev-code.js +1 -1
  44. package/old-names-mask.js +206 -0
  45. package/old-names.js +145 -0
  46. package/package.json +8 -2
  47. package/push-diff.js +2 -2
  48. package/repo-rules/packages.js +5 -5
  49. package/repo-rules.js +2 -2
  50. package/rules/convex-index-name.js +3 -1
  51. package/rules/convex-internal-only.js +2 -1
  52. package/rules/{convex-no-deprecated-crons.js → convex-no-hourly-daily-crons.js} +8 -7
  53. package/rules/convex-runtime-imports.js +2 -1
  54. package/rules/{no-legacy-compat.js → no-underscore-reexport.js} +1 -1
  55. package/slop.js +4 -2
  56. package/ui-rules-css.js +221 -0
  57. package/ui-rules-markup.js +130 -0
  58. package/ui-rules.js +98 -25
  59. package/vendor/old-names-words.js +9 -0
  60. package/rules/no-relative-type-imports.js +0 -40
@@ -0,0 +1,152 @@
1
+ /** The French banned phrases. */
2
+ export const phrasesFr = [
3
+ // --- French: throat-clearing openers ---
4
+ "il est important de noter",
5
+ "il convient de souligner",
6
+ "il est essentiel de",
7
+ "force est de constater",
8
+ "il va sans dire",
9
+ "dans un monde où",
10
+ "à l'ère du",
11
+ "à l'heure où",
12
+ "dans le paysage actuel",
13
+
14
+ // --- French: filler phrases ---
15
+ "en fin de compte",
16
+ "au bout du compte",
17
+ "en d'autres termes",
18
+ "il est à noter que",
19
+ "cela étant dit",
20
+ "dans cette optique",
21
+ "à cet égard",
22
+ "en ce qui concerne",
23
+ "dans le cadre de",
24
+
25
+ // --- French: business jargon phrases ---
26
+ "mise en place",
27
+ "montée en compétence",
28
+ "montée en puissance",
29
+ "retour sur investissement",
30
+ "valeur ajoutée",
31
+ "prise en compte",
32
+ "conduite du changement",
33
+ "transformation digitale",
34
+ "transformation numérique",
35
+ "passage à l'échelle",
36
+ "de pointe",
37
+ "clé en main",
38
+ "sur mesure",
39
+ "de bout en bout",
40
+ "à la pointe",
41
+ "état de l'art",
42
+
43
+ // --- French: AI emphasis crutches ---
44
+ "il ne fait aucun doute",
45
+ "sans aucun doute",
46
+ "il est indéniable",
47
+ "de manière significative",
48
+ "de façon significative",
49
+ "tout au long de",
50
+
51
+ // --- 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 in the `phrases-en-*.js` files.
52
+
53
+ // 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.
54
+
55
+ // Significance asserted instead of stated.
56
+ "constitue un témoignage",
57
+ "témoigne de l'importance",
58
+ "s'impose comme",
59
+ "se présente comme",
60
+ "joue un rôle crucial",
61
+ "joue un rôle clé",
62
+ "joue un rôle majeur",
63
+ "joue un rôle central",
64
+ "un tournant décisif",
65
+ "un moment charnière",
66
+ "une étape clé",
67
+ "marque un tournant",
68
+ "reflète une tendance",
69
+ "s'inscrit dans une dynamique",
70
+ "s'inscrit dans un contexte",
71
+ "contribuant ainsi",
72
+ "mettant en lumière",
73
+ "mettant en avant",
74
+ "met en lumière",
75
+ "met en évidence",
76
+ "souligne l'importance",
77
+ "soulignant l'importance",
78
+
79
+ // Notability asserted instead of shown.
80
+ "sources fiables et indépendantes",
81
+ "de nombreux médias",
82
+ "largement relayé",
83
+ "largement médiatisé",
84
+ "présence active sur les réseaux",
85
+
86
+ // The travel-guide register.
87
+ "au cœur de",
88
+ "niché au cœur",
89
+ "riche patrimoine",
90
+ "patrimoine culturel riche",
91
+ "beauté naturelle",
92
+ "un large éventail",
93
+ "une large gamme",
94
+ "un aperçu fascinant",
95
+ "des informations précieuses",
96
+ "en résonance avec",
97
+
98
+ // The formulaic closing section.
99
+ "malgré ces défis",
100
+ "malgré ces obstacles",
101
+ "fait face à plusieurs défis",
102
+ "de nombreux défis",
103
+ "défis et perspectives",
104
+ "perspectives d'avenir",
105
+ "prix et distinctions",
106
+
107
+ // The section summary.
108
+ "en résumé",
109
+ "pour résumer",
110
+ "en somme",
111
+ "pour conclure",
112
+
113
+ // The disclaimer aimed at an imagined reader.
114
+ "il est crucial de",
115
+ "il est primordial de",
116
+ "il est intéressant de noter",
117
+ "il est bon de noter",
118
+ "il convient de noter",
119
+ "il est utile de rappeler",
120
+ "peut varier selon",
121
+
122
+ // The chatbot's own turn, left in the copy.
123
+ "en tant qu'ia",
124
+ "en tant que modèle de langage",
125
+ "je ne peux pas fournir",
126
+ "je suis désolé, mais",
127
+ "vous avez tout à fait raison",
128
+ "excellente question",
129
+ "souhaitez-vous que je",
130
+ "y a-t-il autre chose",
131
+ "voici un aperçu détaillé",
132
+ "voici une version",
133
+ "j'espère que cela vous aidera",
134
+ "n'hésitez pas à me solliciter",
135
+
136
+ // The model speculating about its own gaps.
137
+ "à ma dernière mise à jour",
138
+ "selon les informations disponibles",
139
+ "d'après les informations disponibles",
140
+ "les détails sont limités",
141
+ "peu de sources",
142
+ "n'est pas largement documenté",
143
+ "n'est pas publiquement disponible",
144
+
145
+ // A relationship alluded to, never stated.
146
+ "en lien avec",
147
+ "en association avec",
148
+ "largement associé",
149
+ "étroitement associé",
150
+ "souvent associé",
151
+ "largement interprété comme",
152
+ ];
@@ -0,0 +1,81 @@
1
+ /** Sentence shapes judged by density, so one instance is style and none can be a pattern. */
2
+ export const shapesDensity = [
3
+ // --- 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.
4
+
5
+ // All seven are density-judged, so none can move into `patterns`: one instance is style.
6
+ {
7
+ id: "semantic-incoherence",
8
+ name: "Semantic incoherence",
9
+ 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.",
10
+ example:
11
+ '"Two overarching pillars undergird the approach." / "the offensive, nestled amid a year of war" / "silence like a thunderstorm folded into velvet"',
12
+ },
13
+ {
14
+ id: "figure-stacking",
15
+ name: "Figure stacking",
16
+ 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.",
17
+ example:
18
+ '"It bit like a thousand tiny teeth, a cruel lover, a quiet violence made beautiful." / "brittle and sharp" / "pastel and brittle"',
19
+ },
20
+ {
21
+ id: "base-adjective-recycling",
22
+ name: "Base adjective recycling",
23
+ 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.",
24
+ example: '"The room was quiet. Her voice was quiet. A quiet dread settled."',
25
+ },
26
+ {
27
+ id: "emotional-flatlining",
28
+ name: "Emotional flatlining",
29
+ 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.",
30
+ example:
31
+ '"A breakfast scene and a betrayal written at the same pitch." / A case study whose setup, turn and result all land equally hard.',
32
+ },
33
+ {
34
+ id: "asserted-transition",
35
+ name: "Asserted transition",
36
+ 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.",
37
+ example:
38
+ '"The region gets heavy rainfall. However, agriculture is a major industry." / "The city has 50,000 people. Moreover, it is near the coast."',
39
+ },
40
+ {
41
+ id: "unsupported-opening-claim",
42
+ name: "Unsupported opening claim",
43
+ 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.",
44
+ example:
45
+ '"The rise of AI is one of the most profound transformations in human history, reshaping industries, societies and our understanding of intelligence."',
46
+ },
47
+ {
48
+ id: "compare-by-restating",
49
+ name: "Compare by restating",
50
+ 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.",
51
+ example:
52
+ '"Her lipstick is red, not just red but vivid, the kind of colour that demands attention." / "hoops, the kind that no one second-guesses"',
53
+ },
54
+ {
55
+ id: "named-feeling",
56
+ name: "Named feeling",
57
+ 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.',
58
+ example:
59
+ '"I was frustrated." / "It was exciting." / "I felt proud of what we built." / "It was a humbling experience."',
60
+ },
61
+ {
62
+ id: "clean-resolution",
63
+ name: "Clean resolution",
64
+ 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.",
65
+ example:
66
+ '"And that is when it all clicked." / "Looking back, I would not change a thing." / "The lesson here is simple."',
67
+ },
68
+ {
69
+ id: "smoothed-figure",
70
+ name: "Smoothed figure",
71
+ 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.',
72
+ example: '"about 50% faster" / "roughly 3x the output" / "around $10k a month"',
73
+ },
74
+ {
75
+ id: "costless-claim",
76
+ name: "Costless claim",
77
+ 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.",
78
+ example:
79
+ '"Always validate before you build." with no account of the thing the writer built and nobody wanted.',
80
+ },
81
+ ];
@@ -0,0 +1,101 @@
1
+ /** Sentence shapes, second third: framing, aphorism and abstraction tells. */
2
+ export const shapesFraming = [
3
+ {
4
+ id: "tells-you-more-than",
5
+ name: "The diagnostic-tell close",
6
+ 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.",
7
+ example:
8
+ '"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."',
9
+ },
10
+ {
11
+ id: "chiastic-reveal",
12
+ name: "Chiastic reveal",
13
+ 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.",
14
+ example:
15
+ '"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."',
16
+ },
17
+ {
18
+ id: "appositive-fragment",
19
+ name: "Appositive fragment",
20
+ 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.",
21
+ example:
22
+ '"One line, nothing dramatic." / "A single question, no pressure." / "Two fields, nothing fancy."',
23
+ },
24
+ {
25
+ id: "imperative-payoff",
26
+ name: "Imperative with a restated payoff",
27
+ 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".',
28
+ example:
29
+ '"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"',
30
+ },
31
+ {
32
+ id: "moral-aphorism",
33
+ name: "Moral aphorism",
34
+ 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.",
35
+ example:
36
+ '"Politeness is free, so it gets treated as free." / "Trust is earned in drops." / "Urgency is a choice."',
37
+ },
38
+ {
39
+ id: "definitional-demotion",
40
+ name: "Definitional demotion",
41
+ 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.',
42
+ example:
43
+ '"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."',
44
+ },
45
+ {
46
+ id: "hypothetical-law",
47
+ name: "Hypothetical law",
48
+ 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.',
49
+ example:
50
+ '"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."',
51
+ },
52
+ {
53
+ id: "colon-connector",
54
+ name: "Colon as a connector",
55
+ 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.",
56
+ example:
57
+ '"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."',
58
+ },
59
+ {
60
+ id: "abstract-metaphor-noun",
61
+ name: "Abstract metaphor noun",
62
+ 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.",
63
+ example:
64
+ '"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."',
65
+ },
66
+ {
67
+ id: "feeling-not-mechanism",
68
+ name: "Feeling instead of mechanism",
69
+ 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.',
70
+ example:
71
+ '"The database stays close at hand." / "SQL you can actually read." / "Types that follow your schema." / "Built for teams that move fast."',
72
+ },
73
+ {
74
+ id: "applause-line",
75
+ name: "Applause line",
76
+ 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.',
77
+ example:
78
+ '"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!"',
79
+ },
80
+ {
81
+ id: "propped-adverb",
82
+ name: "Propped adverb",
83
+ 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.",
84
+ example:
85
+ '"Significantly improves load time." / "Runs quickly on modest hardware." / "Dramatically reduces the number of steps."',
86
+ },
87
+ {
88
+ id: "long-sentence",
89
+ name: "Sentence past 30 words",
90
+ 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.",
91
+ example:
92
+ '"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)',
93
+ },
94
+ {
95
+ id: "spelled-out-number",
96
+ name: "Spelled-out number",
97
+ 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.',
98
+ example:
99
+ '"fifteen clients in and nothing is written down" / "three hours a week" / "a sixty second read" / "twenty per cent of the pipeline"',
100
+ },
101
+ ];
@@ -0,0 +1,88 @@
1
+ /** Sentence shapes, first third: reveals, pivots, closers and the cadence tells. */
2
+ export const shapesReveals = [
3
+ {
4
+ id: "negation-pivot",
5
+ name: "Negation pivot",
6
+ 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`.',
7
+ example:
8
+ '"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."',
9
+ },
10
+ {
11
+ id: "deadpan-closer",
12
+ name: "Deadpan closer",
13
+ 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.",
14
+ example:
15
+ '"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."',
16
+ },
17
+ {
18
+ id: "promised-outcome-as-fact",
19
+ name: "Promised outcome stated as fact",
20
+ 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.',
21
+ example:
22
+ '"Customers reach you on your phone" / "People in your town find you on Google" / "ChatGPT names you when somebody asks" / "Clients pay on time"',
23
+ },
24
+ {
25
+ id: "self-acting-abstraction",
26
+ name: "Self-acting abstraction",
27
+ 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.',
28
+ example:
29
+ '"Tasks that write themselves" / "The week plans itself" / "A calendar takes them" / "Calls become task updates on their own" / "a workspace that runs itself"',
30
+ },
31
+ {
32
+ id: "comma-hung-fragment",
33
+ name: "Comma-hung fragment",
34
+ 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".',
35
+ example:
36
+ '"Sales tax report, filed" / "The week, planned" / "4 to 5 hours a week, back" / "One line, nothing dramatic"',
37
+ },
38
+ {
39
+ id: "correlative-inflation",
40
+ name: "Correlative inflation",
41
+ rule: "Stacked correlative pairs used to make one idea sound like two.",
42
+ example: '"not only X but also Y" / "both X and Y" where only X is doing work',
43
+ },
44
+ {
45
+ id: "rule-of-three",
46
+ name: "Rule of three",
47
+ rule: "Three-item lists where the third item exists only for rhythm. Cut it or make it load-bearing.",
48
+ example: '"faster, cleaner, and more reliable"',
49
+ },
50
+ {
51
+ id: "superficial-ing-analysis",
52
+ name: "Superficial -ing analysis",
53
+ rule: "A trailing participial clause that restates the sentence as significance instead of adding a fact.",
54
+ example: '"..., highlighting the importance of clear processes."',
55
+ },
56
+ {
57
+ id: "engagement-bait-close",
58
+ name: "Engagement-bait close",
59
+ rule: "A question bolted onto the end with no real offer behind it. End on the idea, or on one specific real ask.",
60
+ example: '"What do you think?" / "How do you handle this? Let me know below."',
61
+ },
62
+ {
63
+ id: "selfish-framing",
64
+ name: "Selfish framing",
65
+ 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.',
66
+ example: '"We are excited to share our new approach." / "Mine is day 21."',
67
+ },
68
+ {
69
+ id: "dramatized-pain",
70
+ name: "Dramatized pain",
71
+ rule: "Inflating the reader's problem past what they would call it themselves.",
72
+ example: '"operational nightmare" / "a complete disaster"',
73
+ },
74
+ {
75
+ id: "the-part-nobody",
76
+ name: "The unclaimed-insight preamble",
77
+ 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.",
78
+ example:
79
+ '"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."',
80
+ },
81
+ {
82
+ id: "nobody-universal",
83
+ name: "The invented universal",
84
+ 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".',
85
+ example:
86
+ '"and nobody writes it down" / "Nobody checks the numbers." / "Nobody reads the handbook." / "Everyone does it, and nobody measures it."',
87
+ },
88
+ ];
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Checked on titles and headings only: a comma there is cadence standing in for
3
+ * a subject. A colon that labels the subject is fine. Home of `course-lint`'s rule.
4
+ */
5
+ export const titleTells = [
6
+ { id: "title-comma", test: /,/, rule: "comma in a title (one clause, no second beat)" },
7
+ { id: "title-not-y", test: /,\s+not\s+/i, rule: '"X, not Y" antithesis' },
8
+ ];
@@ -0,0 +1,178 @@
1
+ /** The English bans. Exported apart so an English-only surface can skip the French. */
2
+ export const wordsEn = [
3
+ // --- Existing workspace bans ---
4
+ "foster",
5
+ "fostering",
6
+ "transformative",
7
+ "navigating",
8
+ "navigate",
9
+ "seamless",
10
+ "seamlessly",
11
+ "unleash",
12
+ "enhance",
13
+ "enhancing",
14
+ "embrace",
15
+ "embracing",
16
+ "ensure",
17
+ "ensuring",
18
+ "encourage",
19
+ "encouraging",
20
+ "continuous",
21
+ "utilizing",
22
+ "utilize",
23
+ "comprehensive",
24
+ "leveraging",
25
+ "leverage",
26
+ "enable",
27
+ "enabling",
28
+ "streamline",
29
+ "streamlining",
30
+ "efficiency",
31
+ "versatile",
32
+ "tailor",
33
+ "tailored",
34
+ "conduct",
35
+
36
+ // --- 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.
37
+
38
+ // "chase" survives once, as a plain verb inside "chase payment". The gerund is a copywriter's word, not his.
39
+ "chasing",
40
+
41
+ // --- 2026 corpus: the register words named repeatedly across 31 videos on AI writing, read 6 Sep 2026.
42
+
43
+ // `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
44
+
45
+ // be neutral. Evidence: humanizer/references/detection.md.
46
+ "quietly",
47
+ "amid",
48
+ "commendable",
49
+ "breathtaking",
50
+ "scenic",
51
+ "sleek",
52
+
53
+ // --- Stop-slop: business jargon ---
54
+ "actionable",
55
+ "beacon",
56
+ "bespoke",
57
+ "bolster",
58
+ "catalyst",
59
+ "cornerstone",
60
+ "curate",
61
+ "curated",
62
+ "delve",
63
+ "delving",
64
+ "disruptive",
65
+ "ecosystem",
66
+ "elevate",
67
+ "elevating",
68
+ "embark",
69
+ "embarking",
70
+ "empower",
71
+ "empowering",
72
+ "facilitate",
73
+ "facilitating",
74
+ "groundbreaking",
75
+ "harness",
76
+ "harnessing",
77
+ "holistic",
78
+ "innovative",
79
+ "intricate",
80
+ "intricacies",
81
+ "landscape",
82
+ "meticulous",
83
+ "meticulously",
84
+ "multifaceted",
85
+ "myriad",
86
+ "nuanced",
87
+ "optimize",
88
+ "optimizing",
89
+ "paramount",
90
+ "paradigm",
91
+ "pivotal",
92
+ "payoff",
93
+ "plethora",
94
+ "poised",
95
+ "realm",
96
+ "redefine",
97
+ "redefining",
98
+ "reimagine",
99
+ "reimagining",
100
+ "reshape",
101
+ "reshaping",
102
+ "revolutionize",
103
+ "revolutionizing",
104
+ "robust",
105
+ "scalable",
106
+ "spearhead",
107
+ "synergy",
108
+ "tapestry",
109
+ "testament",
110
+ "underpin",
111
+ "underscore",
112
+ "unpack",
113
+ "unpacking",
114
+
115
+ // --- Stop-slop: adverbs (AI tells) ---
116
+ "crucially",
117
+ "deeply",
118
+ "fundamentally",
119
+ "furthermore",
120
+ "genuinely",
121
+ "importantly",
122
+ "inevitably",
123
+ "inherently",
124
+ "interestingly",
125
+ "moreover",
126
+ "truly",
127
+ "ultimately",
128
+
129
+ // --- petergyang/no-ai-slop, read 2026-08-31 --- The six surface forms that list carries and this one did not.
130
+
131
+ // 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.
132
+
133
+ // "highlighting" and "reflecting" are deliberately absent: both are ordinary English, so the trailing -ing analysis clause stays a human read against patterns.md 3.
134
+
135
+ // Zero occurrences of all six across the first-party corpus.
136
+ "showcasing",
137
+ "underscores",
138
+ "underscoring",
139
+ "supercharge",
140
+ "supercharging",
141
+ "ever-evolving",
142
+
143
+ // --- Wikipedia:Signs of AI writing, "AI vocabulary", read 2026-09-05 --- The words-to-watch that list carries and this one did not.
144
+
145
+ // "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 and the Wikipedia section on undue emphasis.
146
+ "additionally",
147
+ "boast",
148
+ "boasts",
149
+ "bolstered",
150
+ "cementing",
151
+ "crucial",
152
+ "cultivating",
153
+ "emphasizing",
154
+ "emphasises",
155
+ "emphasizes",
156
+ "encompassing",
157
+ "enduring",
158
+ "epitomizes",
159
+ "exemplifies",
160
+ "exemplifying",
161
+ "garner",
162
+ "garnered",
163
+ "garnering",
164
+ "interplay",
165
+ "nestled",
166
+ "profound",
167
+ "renowned",
168
+ "resonate",
169
+ "resonates",
170
+ "showcase",
171
+ "showcases",
172
+ "solidifying",
173
+ "symbolizing",
174
+ "underpinning",
175
+ "underpins",
176
+ "valuable",
177
+ "vibrant",
178
+ ];