opengrammar-server 2.0.615350

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 (53) hide show
  1. package/README.npm.md +95 -0
  2. package/bin/opengrammar-server.js +111 -0
  3. package/dist/server.js +48639 -0
  4. package/package.json +80 -0
  5. package/server-node.ts +159 -0
  6. package/server.ts +15 -0
  7. package/src/analyzer.ts +542 -0
  8. package/src/dictionary.ts +1973 -0
  9. package/src/index.ts +978 -0
  10. package/src/nlp/nlp-engine.ts +17 -0
  11. package/src/nlp/tone-analyzer.ts +269 -0
  12. package/src/rephraser.ts +146 -0
  13. package/src/rules/categories/academic-writing.ts +182 -0
  14. package/src/rules/categories/adjectives-adverbs.ts +152 -0
  15. package/src/rules/categories/articles.ts +160 -0
  16. package/src/rules/categories/business-writing.ts +250 -0
  17. package/src/rules/categories/capitalization.ts +79 -0
  18. package/src/rules/categories/clarity.ts +117 -0
  19. package/src/rules/categories/common-errors.ts +601 -0
  20. package/src/rules/categories/confused-words.ts +219 -0
  21. package/src/rules/categories/conjunctions.ts +176 -0
  22. package/src/rules/categories/dangling-modifiers.ts +123 -0
  23. package/src/rules/categories/formality.ts +274 -0
  24. package/src/rules/categories/formatting-idioms.ts +323 -0
  25. package/src/rules/categories/gerund-infinitive.ts +274 -0
  26. package/src/rules/categories/grammar-advanced.ts +294 -0
  27. package/src/rules/categories/grammar.ts +286 -0
  28. package/src/rules/categories/inclusive-language.ts +280 -0
  29. package/src/rules/categories/nouns-pronouns.ts +233 -0
  30. package/src/rules/categories/prepositions-extended.ts +217 -0
  31. package/src/rules/categories/prepositions.ts +159 -0
  32. package/src/rules/categories/punctuation.ts +347 -0
  33. package/src/rules/categories/quantity-agreement.ts +200 -0
  34. package/src/rules/categories/readability.ts +293 -0
  35. package/src/rules/categories/sentence-structure.ts +100 -0
  36. package/src/rules/categories/spelling-advanced.ts +164 -0
  37. package/src/rules/categories/spelling.ts +119 -0
  38. package/src/rules/categories/style-tone.ts +511 -0
  39. package/src/rules/categories/style.ts +78 -0
  40. package/src/rules/categories/subject-verb-agreement.ts +201 -0
  41. package/src/rules/categories/tone-rules.ts +206 -0
  42. package/src/rules/categories/verb-tense.ts +582 -0
  43. package/src/rules/context-filter.ts +446 -0
  44. package/src/rules/index.ts +96 -0
  45. package/src/rules/ruleset-part1-cj-pu-sp.json +657 -0
  46. package/src/rules/ruleset-part1-np-ad-aa-pr.json +831 -0
  47. package/src/rules/ruleset-part1-ss-vt.json +907 -0
  48. package/src/rules/ruleset-part2-cw-st-nf.json +318 -0
  49. package/src/rules/ruleset-part3-aw-bw-il-rd.json +161 -0
  50. package/src/rules/types.ts +79 -0
  51. package/src/shared-types.ts +152 -0
  52. package/src/spellchecker.ts +418 -0
  53. package/tsconfig.json +25 -0
@@ -0,0 +1,582 @@
1
+ import type { Issue } from '../../shared-types.js';
2
+ import { createRegexRule, type Rule } from '../types.js';
3
+
4
+ export const verbTenseRules: Rule[] = [
5
+ // ═══ Irregular Verb Errors — Extended (VT_IRR) ═══
6
+ // Past tense regularization errors (extending grammar.ts)
7
+ createRegexRule({
8
+ id: 'VT_drived',
9
+ category: 'grammar',
10
+ pattern: /\bdrived\b/i,
11
+ suggestion: 'drove',
12
+ reason: '"Drived" is not a word. The past tense of "drive" is "drove".',
13
+ }),
14
+ createRegexRule({
15
+ id: 'VT_speaked',
16
+ category: 'grammar',
17
+ pattern: /\bspeaked\b/i,
18
+ suggestion: 'spoke',
19
+ reason: '"Speaked" is not a word. The past tense of "speak" is "spoke".',
20
+ }),
21
+ createRegexRule({
22
+ id: 'VT_writed',
23
+ category: 'grammar',
24
+ pattern: /\bwrited\b/i,
25
+ suggestion: 'wrote',
26
+ reason: '"Writed" is not a word. The past tense of "write" is "wrote".',
27
+ }),
28
+ createRegexRule({
29
+ id: 'VT_beginned',
30
+ category: 'grammar',
31
+ pattern: /\bbeginned\b/i,
32
+ suggestion: 'began',
33
+ reason: '"Beginned" is not a word. The past tense of "begin" is "began".',
34
+ }),
35
+ createRegexRule({
36
+ id: 'VT_choosed',
37
+ category: 'grammar',
38
+ pattern: /\bchoosed\b/i,
39
+ suggestion: 'chose',
40
+ reason: '"Choosed" is not a word. The past tense of "choose" is "chose".',
41
+ }),
42
+ createRegexRule({
43
+ id: 'VT_drinked',
44
+ category: 'grammar',
45
+ pattern: /\bdrinked\b/i,
46
+ suggestion: 'drank',
47
+ reason: '"Drinked" is not a word. The past tense of "drink" is "drank".',
48
+ }),
49
+ createRegexRule({
50
+ id: 'VT_flyed',
51
+ category: 'grammar',
52
+ pattern: /\bflyed\b/i,
53
+ suggestion: 'flew',
54
+ reason: '"Flyed" is not a word. The past tense of "fly" is "flew".',
55
+ }),
56
+ createRegexRule({
57
+ id: 'VT_freezed',
58
+ category: 'grammar',
59
+ pattern: /\bfreezed\b/i,
60
+ suggestion: 'froze',
61
+ reason: '"Freezed" is not a word. The past tense of "freeze" is "froze".',
62
+ }),
63
+ createRegexRule({
64
+ id: 'VT_growed',
65
+ category: 'grammar',
66
+ pattern: /\bgrowed\b/i,
67
+ suggestion: 'grew',
68
+ reason: '"Growed" is not a word. The past tense of "grow" is "grew".',
69
+ }),
70
+ createRegexRule({
71
+ id: 'VT_hided',
72
+ category: 'grammar',
73
+ pattern: /\bhided\b/i,
74
+ suggestion: 'hid',
75
+ reason: '"Hided" is not a word. The past tense of "hide" is "hid".',
76
+ }),
77
+ createRegexRule({
78
+ id: 'VT_leaved',
79
+ category: 'grammar',
80
+ pattern: /\bleaved\b/i,
81
+ suggestion: 'left',
82
+ reason: '"Leaved" is not a word. The past tense of "leave" is "left".',
83
+ }),
84
+ createRegexRule({
85
+ id: 'VT_meaned',
86
+ category: 'grammar',
87
+ pattern: /\bmeaned\b/i,
88
+ suggestion: 'meant',
89
+ reason: '"Meaned" is not a word. The past tense of "mean" is "meant".',
90
+ }),
91
+ createRegexRule({
92
+ id: 'VT_selled',
93
+ category: 'grammar',
94
+ pattern: /\bselled\b/i,
95
+ suggestion: 'sold',
96
+ reason: '"Selled" is not a word. The past tense of "sell" is "sold".',
97
+ }),
98
+ createRegexRule({
99
+ id: 'VT_sitted',
100
+ category: 'grammar',
101
+ pattern: /\bsitted\b/i,
102
+ suggestion: 'sat',
103
+ reason: '"Sitted" is not a word. The past tense of "sit" is "sat".',
104
+ }),
105
+ createRegexRule({
106
+ id: 'VT_sleeped',
107
+ category: 'grammar',
108
+ pattern: /\bsleeped\b/i,
109
+ suggestion: 'slept',
110
+ reason: '"Sleeped" is not a word. The past tense of "sleep" is "slept".',
111
+ }),
112
+ createRegexRule({
113
+ id: 'VT_stealed',
114
+ category: 'grammar',
115
+ pattern: /\bstealed\b/i,
116
+ suggestion: 'stole',
117
+ reason: '"Stealed" is not a word. The past tense of "steal" is "stole".',
118
+ }),
119
+ createRegexRule({
120
+ id: 'VT_swimmed',
121
+ category: 'grammar',
122
+ pattern: /\bswimmed\b/i,
123
+ suggestion: 'swam',
124
+ reason: '"Swimmed" is not a word. The past tense of "swim" is "swam".',
125
+ }),
126
+ createRegexRule({
127
+ id: 'VT_teached',
128
+ category: 'grammar',
129
+ pattern: /\bteached\b/i,
130
+ suggestion: 'taught',
131
+ reason: '"Teached" is not a word. The past tense of "teach" is "taught".',
132
+ }),
133
+ createRegexRule({
134
+ id: 'VT_throwed',
135
+ category: 'grammar',
136
+ pattern: /\bthrowed\b/i,
137
+ suggestion: 'threw',
138
+ reason: '"Throwed" is not a word. The past tense of "throw" is "threw".',
139
+ }),
140
+ createRegexRule({
141
+ id: 'VT_weared',
142
+ category: 'grammar',
143
+ pattern: /\bweared\b/i,
144
+ suggestion: 'wore',
145
+ reason: '"Weared" is not a word. The past tense of "wear" is "wore".',
146
+ }),
147
+ createRegexRule({
148
+ id: 'VT_winned',
149
+ category: 'grammar',
150
+ pattern: /\bwinned\b/i,
151
+ suggestion: 'won',
152
+ reason: '"Winned" is not a word. The past tense of "win" is "won".',
153
+ }),
154
+ createRegexRule({
155
+ id: 'VT_catched',
156
+ category: 'grammar',
157
+ pattern: /\bcatched\b/i,
158
+ suggestion: 'caught',
159
+ reason: '"Catched" is not a word. The past tense of "catch" is "caught".',
160
+ }),
161
+ createRegexRule({
162
+ id: 'VT_fighted',
163
+ category: 'grammar',
164
+ pattern: /\bfighted\b/i,
165
+ suggestion: 'fought',
166
+ reason: '"Fighted" is not a word. The past tense of "fight" is "fought".',
167
+ }),
168
+ createRegexRule({
169
+ id: 'VT_feeled',
170
+ category: 'grammar',
171
+ pattern: /\bfeeled\b/i,
172
+ suggestion: 'felt',
173
+ reason: '"Feeled" is not a word. The past tense of "feel" is "felt".',
174
+ }),
175
+ createRegexRule({
176
+ id: 'VT_finded',
177
+ category: 'grammar',
178
+ pattern: /\bfinded\b/i,
179
+ suggestion: 'found',
180
+ reason: '"Finded" is not a word. The past tense of "find" is "found".',
181
+ }),
182
+ createRegexRule({
183
+ id: 'VT_forgetted',
184
+ category: 'grammar',
185
+ pattern: /\bforgetted\b/i,
186
+ suggestion: 'forgot',
187
+ reason: '"Forgetted" is not a word. The past tense of "forget" is "forgot".',
188
+ }),
189
+ createRegexRule({
190
+ id: 'VT_gived',
191
+ category: 'grammar',
192
+ pattern: /\bgived\b/i,
193
+ suggestion: 'gave',
194
+ reason: '"Gived" is not a word. The past tense of "give" is "gave".',
195
+ }),
196
+ createRegexRule({
197
+ id: 'VT_heared',
198
+ category: 'grammar',
199
+ pattern: /\bheared\b/i,
200
+ suggestion: 'heard',
201
+ reason: '"Heared" is not a word. The past tense of "hear" is "heard".',
202
+ }),
203
+ createRegexRule({
204
+ id: 'VT_holded',
205
+ category: 'grammar',
206
+ pattern: /\bholded\b/i,
207
+ suggestion: 'held',
208
+ reason: '"Holded" is not a word. The past tense of "hold" is "held".',
209
+ }),
210
+ createRegexRule({
211
+ id: 'VT_keeped',
212
+ category: 'grammar',
213
+ pattern: /\bkeeped\b/i,
214
+ suggestion: 'kept',
215
+ reason: '"Keeped" is not a word. The past tense of "keep" is "kept".',
216
+ }),
217
+ createRegexRule({
218
+ id: 'VT_losted',
219
+ category: 'grammar',
220
+ pattern: /\blosted\b/i,
221
+ suggestion: 'lost',
222
+ reason: '"Losted" is not a word. The past tense of "lose" is "lost".',
223
+ }),
224
+ createRegexRule({
225
+ id: 'VT_maked',
226
+ category: 'grammar',
227
+ pattern: /\bmaked\b/i,
228
+ suggestion: 'made',
229
+ reason: '"Maked" is not a word. The past tense of "make" is "made".',
230
+ }),
231
+ createRegexRule({
232
+ id: 'VT_sayed',
233
+ category: 'grammar',
234
+ pattern: /\bsayed\b/i,
235
+ suggestion: 'said',
236
+ reason: '"Sayed" is not a word. The past tense of "say" is "said".',
237
+ }),
238
+ createRegexRule({
239
+ id: 'VT_sended',
240
+ category: 'grammar',
241
+ pattern: /\bsended\b/i,
242
+ suggestion: 'sent',
243
+ reason: '"Sended" is not a word. The past tense of "send" is "sent".',
244
+ }),
245
+ createRegexRule({
246
+ id: 'VT_spended',
247
+ category: 'grammar',
248
+ pattern: /\bspended\b/i,
249
+ suggestion: 'spent',
250
+ reason: '"Spended" is not a word. The past tense of "spend" is "spent".',
251
+ }),
252
+ createRegexRule({
253
+ id: 'VT_standed',
254
+ category: 'grammar',
255
+ pattern: /\bstanded\b/i,
256
+ suggestion: 'stood',
257
+ reason: '"Standed" is not a word. The past tense of "stand" is "stood".',
258
+ }),
259
+ createRegexRule({
260
+ id: 'VT_telled',
261
+ category: 'grammar',
262
+ pattern: /\btelled\b/i,
263
+ suggestion: 'told',
264
+ reason: '"Telled" is not a word. The past tense of "tell" is "told".',
265
+ }),
266
+
267
+ // ═══ Modal Perfect Errors (VT_MOD_001) ═══
268
+ createRegexRule({
269
+ id: 'VT_MOD_went',
270
+ category: 'grammar',
271
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+went\b/i,
272
+ suggestion: (m) => `${m[1]} have gone`,
273
+ reason: 'After "modal + have", use the past participle: "gone", not "went".',
274
+ }),
275
+ createRegexRule({
276
+ id: 'VT_MOD_ran',
277
+ category: 'grammar',
278
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+ran\b/i,
279
+ suggestion: (m) => `${m[1]} have run`,
280
+ reason: 'After "modal + have", use the past participle: "run", not "ran".',
281
+ }),
282
+ createRegexRule({
283
+ id: 'VT_MOD_ate',
284
+ category: 'grammar',
285
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+ate\b/i,
286
+ suggestion: (m) => `${m[1]} have eaten`,
287
+ reason: 'After "modal + have", use the past participle: "eaten", not "ate".',
288
+ }),
289
+ createRegexRule({
290
+ id: 'VT_MOD_drove',
291
+ category: 'grammar',
292
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+drove\b/i,
293
+ suggestion: (m) => `${m[1]} have driven`,
294
+ reason: 'After "modal + have", use the past participle: "driven", not "drove".',
295
+ }),
296
+ createRegexRule({
297
+ id: 'VT_MOD_spoke',
298
+ category: 'grammar',
299
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+spoke\b/i,
300
+ suggestion: (m) => `${m[1]} have spoken`,
301
+ reason: 'After "modal + have", use the past participle: "spoken", not "spoke".',
302
+ }),
303
+ createRegexRule({
304
+ id: 'VT_MOD_wrote',
305
+ category: 'grammar',
306
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+wrote\b/i,
307
+ suggestion: (m) => `${m[1]} have written`,
308
+ reason: 'After "modal + have", use the past participle: "written", not "wrote".',
309
+ }),
310
+ createRegexRule({
311
+ id: 'VT_MOD_broke',
312
+ category: 'grammar',
313
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+broke\b/i,
314
+ suggestion: (m) => `${m[1]} have broken`,
315
+ reason: 'After "modal + have", use the past participle: "broken", not "broke".',
316
+ }),
317
+ createRegexRule({
318
+ id: 'VT_MOD_took',
319
+ category: 'grammar',
320
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+took\b/i,
321
+ suggestion: (m) => `${m[1]} have taken`,
322
+ reason: 'After "modal + have", use the past participle: "taken", not "took".',
323
+ }),
324
+ createRegexRule({
325
+ id: 'VT_MOD_saw',
326
+ category: 'grammar',
327
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+saw\b/i,
328
+ suggestion: (m) => `${m[1]} have seen`,
329
+ reason: 'After "modal + have", use the past participle: "seen", not "saw".',
330
+ }),
331
+ createRegexRule({
332
+ id: 'VT_MOD_gave',
333
+ category: 'grammar',
334
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+gave\b/i,
335
+ suggestion: (m) => `${m[1]} have given`,
336
+ reason: 'After "modal + have", use the past participle: "given", not "gave".',
337
+ }),
338
+ createRegexRule({
339
+ id: 'VT_MOD_came',
340
+ category: 'grammar',
341
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+came\b/i,
342
+ suggestion: (m) => `${m[1]} have come`,
343
+ reason: 'After "modal + have", use the past participle: "come", not "came".',
344
+ }),
345
+ createRegexRule({
346
+ id: 'VT_MOD_did',
347
+ category: 'grammar',
348
+ pattern: /\b(should|could|would|might|must|may)\s+have\s+did\b/i,
349
+ suggestion: (m) => `${m[1]} have done`,
350
+ reason: 'After "modal + have", use the past participle: "done", not "did".',
351
+ }),
352
+
353
+ // ═══ Have + wrong participle (VT_IRR_002) ═══
354
+ createRegexRule({
355
+ id: 'VT_have_went',
356
+ category: 'grammar',
357
+ pattern: /\b(have|has|had)\s+went\b/i,
358
+ suggestion: (m) => `${m[1]} gone`,
359
+ reason: 'Use past participle "gone" after have/has/had, not "went".',
360
+ }),
361
+ createRegexRule({
362
+ id: 'VT_have_ate',
363
+ category: 'grammar',
364
+ pattern: /\b(have|has|had)\s+ate\b/i,
365
+ suggestion: (m) => `${m[1]} eaten`,
366
+ reason: 'Use past participle "eaten" after have/has/had, not "ate".',
367
+ }),
368
+ createRegexRule({
369
+ id: 'VT_have_drove',
370
+ category: 'grammar',
371
+ pattern: /\b(have|has|had)\s+drove\b/i,
372
+ suggestion: (m) => `${m[1]} driven`,
373
+ reason: 'Use past participle "driven" after have/has/had.',
374
+ }),
375
+ createRegexRule({
376
+ id: 'VT_have_spoke',
377
+ category: 'grammar',
378
+ pattern: /\b(have|has|had)\s+spoke\b/i,
379
+ suggestion: (m) => `${m[1]} spoken`,
380
+ reason: 'Use past participle "spoken" after have/has/had.',
381
+ }),
382
+ createRegexRule({
383
+ id: 'VT_have_wrote',
384
+ category: 'grammar',
385
+ pattern: /\b(have|has|had)\s+wrote\b/i,
386
+ suggestion: (m) => `${m[1]} written`,
387
+ reason: 'Use past participle "written" after have/has/had.',
388
+ }),
389
+ createRegexRule({
390
+ id: 'VT_have_broke',
391
+ category: 'grammar',
392
+ pattern: /\b(have|has|had)\s+broke\b/i,
393
+ suggestion: (m) => `${m[1]} broken`,
394
+ reason: 'Use past participle "broken" after have/has/had.',
395
+ }),
396
+ createRegexRule({
397
+ id: 'VT_have_took',
398
+ category: 'grammar',
399
+ pattern: /\b(have|has|had)\s+took\b/i,
400
+ suggestion: (m) => `${m[1]} taken`,
401
+ reason: 'Use past participle "taken" after have/has/had.',
402
+ }),
403
+ createRegexRule({
404
+ id: 'VT_have_saw',
405
+ category: 'grammar',
406
+ pattern: /\b(have|has|had)\s+saw\b/i,
407
+ suggestion: (m) => `${m[1]} seen`,
408
+ reason: 'Use past participle "seen" after have/has/had.',
409
+ }),
410
+ createRegexRule({
411
+ id: 'VT_have_ran',
412
+ category: 'grammar',
413
+ pattern: /\b(have|has|had)\s+ran\b/i,
414
+ suggestion: (m) => `${m[1]} run`,
415
+ reason: 'Use past participle "run" after have/has/had.',
416
+ }),
417
+ createRegexRule({
418
+ id: 'VT_have_gave',
419
+ category: 'grammar',
420
+ pattern: /\b(have|has|had)\s+gave\b/i,
421
+ suggestion: (m) => `${m[1]} given`,
422
+ reason: 'Use past participle "given" after have/has/had.',
423
+ }),
424
+ createRegexRule({
425
+ id: 'VT_have_did',
426
+ category: 'grammar',
427
+ pattern: /\b(have|has|had)\s+did\b/i,
428
+ suggestion: (m) => `${m[1]} done`,
429
+ reason: 'Use past participle "done" after have/has/had.',
430
+ }),
431
+ createRegexRule({
432
+ id: 'VT_have_swam',
433
+ category: 'grammar',
434
+ pattern: /\b(have|has|had)\s+swam\b/i,
435
+ suggestion: (m) => `${m[1]} swum`,
436
+ reason: 'Use past participle "swum" after have/has/had.',
437
+ }),
438
+
439
+ // ═══ Subjunctive Mood (VT_SBJ) ═══
440
+ createRegexRule({
441
+ id: 'VT_SBJ_was',
442
+ category: 'grammar',
443
+ pattern: /\b(if|as\s+if|as\s+though|wish|wished)\s+(I|he|she|it)\s+was\b/i,
444
+ suggestion: (m) => `${m[1]} ${m[2]} were`,
445
+ reason: 'In hypothetical conditions, use "were" for all subjects (subjunctive mood).',
446
+ }),
447
+ createRegexRule({
448
+ id: 'VT_SBJ_recommend',
449
+ category: 'grammar',
450
+ pattern:
451
+ /\b(recommend|suggest|demand|insist|request|require|propose|urge)\s+that\s+(he|she|it)\s+(goes|has|is|was|does|takes|makes|gives|comes|leaves|stays|starts|stops|works|plays|reads|writes|runs|eats|drinks|sleeps)\b/i,
452
+ suggestion: (m) =>
453
+ `${m[1]} that ${m[2]} ${(m[3] || '').replace(/s$/, '').replace(/es$/, '').replace('goes', 'go').replace('has', 'have').replace('is', 'be').replace('was', 'be').replace('does', 'do')}`,
454
+ reason:
455
+ 'Use the base form of the verb (no -s) in subjunctive constructions after verbs of demand or recommendation.',
456
+ }),
457
+
458
+ // ═══ Stative Verbs in Progressive (VT_STV) ═══
459
+ createRegexRule({
460
+ id: 'VT_STV_know',
461
+ category: 'grammar',
462
+ pattern: /\b(am|is|are|was|were)\s+knowing\b/i,
463
+ suggestion: (m) =>
464
+ `${({ am: '', is: '', are: '', was: '', were: '' } as Record<string, string>)[m[1]?.toLowerCase() || ''] !== undefined ? (m[1]?.toLowerCase() === 'am' ? 'know' : m[1]?.toLowerCase() === 'is' ? 'knows' : 'know') : 'know'}`,
465
+ reason: '"Know" is a stative verb and should not be used in progressive form.',
466
+ }),
467
+ createRegexRule({
468
+ id: 'VT_STV_believe',
469
+ category: 'grammar',
470
+ pattern: /\b(am|is|are|was|were)\s+believing\b/i,
471
+ suggestion: 'believe',
472
+ reason: '"Believe" is a stative verb. Use simple tense instead.',
473
+ }),
474
+ createRegexRule({
475
+ id: 'VT_STV_own',
476
+ category: 'grammar',
477
+ pattern: /\b(am|is|are|was|were)\s+owning\b/i,
478
+ suggestion: 'own',
479
+ reason: '"Own" is a stative verb. Use "own" instead of "is owning".',
480
+ }),
481
+ createRegexRule({
482
+ id: 'VT_STV_belong',
483
+ category: 'grammar',
484
+ pattern: /\b(am|is|are|was|were)\s+belonging\b/i,
485
+ suggestion: 'belong',
486
+ reason: '"Belong" is a stative verb. Use simple tense.',
487
+ }),
488
+ createRegexRule({
489
+ id: 'VT_STV_consist',
490
+ category: 'grammar',
491
+ pattern: /\b(am|is|are|was|were)\s+consisting\b/i,
492
+ suggestion: 'consist',
493
+ reason: '"Consist" is a stative verb. Use simple tense.',
494
+ }),
495
+ createRegexRule({
496
+ id: 'VT_STV_contain',
497
+ category: 'grammar',
498
+ pattern: /\b(am|is|are|was|were)\s+containing\b/i,
499
+ suggestion: 'contain',
500
+ reason: '"Contain" is a stative verb. Use simple tense.',
501
+ }),
502
+ createRegexRule({
503
+ id: 'VT_STV_depend',
504
+ category: 'grammar',
505
+ pattern: /\b(am|is|are|was|were)\s+depending\b/i,
506
+ suggestion: 'depend',
507
+ reason: '"Depend" is a stative verb. Use "depends on" instead.',
508
+ }),
509
+ createRegexRule({
510
+ id: 'VT_STV_prefer',
511
+ category: 'grammar',
512
+ pattern: /\b(am|is|are|was|were)\s+preferring\b/i,
513
+ suggestion: 'prefer',
514
+ reason: '"Prefer" is a stative verb. Use simple tense.',
515
+ }),
516
+ createRegexRule({
517
+ id: 'VT_STV_seem',
518
+ category: 'grammar',
519
+ pattern: /\b(am|is|are|was|were)\s+seeming\b/i,
520
+ suggestion: 'seem',
521
+ reason: '"Seem" is a stative verb. Use simple tense.',
522
+ }),
523
+ createRegexRule({
524
+ id: 'VT_STV_appear',
525
+ category: 'grammar',
526
+ pattern: /\b(am|is|are|was|were)\s+appearing\b/i,
527
+ suggestion: 'appear',
528
+ reason: '"Appear" is a stative verb (when meaning "seem"). Use simple tense.',
529
+ }),
530
+
531
+ // ═══ Verb + Wrong Preposition Collocations (VT_COL) ═══
532
+ createRegexRule({
533
+ id: 'VT_COL_discuss_about',
534
+ category: 'grammar',
535
+ pattern: /\bdiscuss\s+about\b/i,
536
+ suggestion: 'discuss',
537
+ reason: '"Discuss" is transitive — no "about" needed.',
538
+ }),
539
+ createRegexRule({
540
+ id: 'VT_COL_reach_to',
541
+ category: 'grammar',
542
+ pattern: /\breached?\s+to\s+(the|a|his|her|their|our|my|your|its)\b/i,
543
+ suggestion: (m) => `reached ${m[1]}`,
544
+ reason: '"Reach" is transitive — no "to" needed.',
545
+ }),
546
+ createRegexRule({
547
+ id: 'VT_COL_enter_into',
548
+ category: 'grammar',
549
+ pattern:
550
+ /\bentered?\s+into\s+(the|a|his|her|their|our|my|your|its)\s+(room|house|building|office|store|shop|hall|class|school|hospital|church|kitchen|bedroom|bathroom|garage|garden|park|stadium|theater|theatre|museum|library|restaurant|cafe|bar|club|gym|pool|elevator|lift)b/i,
551
+ suggestion: (m) => `entered ${m[1]} ${m[2]}`,
552
+ reason: '"Enter" is transitive for physical spaces — no "into" needed.',
553
+ }),
554
+ createRegexRule({
555
+ id: 'VT_COL_cope_up',
556
+ category: 'grammar',
557
+ pattern: /\bcope\s+up\s+with\b/i,
558
+ suggestion: 'cope with',
559
+ reason: 'The correct phrase is "cope with", not "cope up with".',
560
+ }),
561
+ createRegexRule({
562
+ id: 'VT_COL_comprise_of',
563
+ category: 'grammar',
564
+ pattern: /\bcomprises?\s+of\b/i,
565
+ suggestion: 'comprises',
566
+ reason: '"Comprises" means "is made up of" — don\'t add "of". Or use "is composed of".',
567
+ }),
568
+ createRegexRule({
569
+ id: 'VT_COL_emphasize_on',
570
+ category: 'grammar',
571
+ pattern: /\bemphasizes?\s+on\b/i,
572
+ suggestion: 'emphasize',
573
+ reason: '"Emphasize" is transitive — no "on" needed.',
574
+ }),
575
+ createRegexRule({
576
+ id: 'VT_COL_mention_about',
577
+ category: 'grammar',
578
+ pattern: /\bmentioned?\s+about\b/i,
579
+ suggestion: 'mentioned',
580
+ reason: '"Mention" is transitive — no "about" needed.',
581
+ }),
582
+ ];