stylemcp 0.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 (83) hide show
  1. package/README.md +261 -0
  2. package/action/action.yml +59 -0
  3. package/action/package.json +24 -0
  4. package/action/src/index.ts +455 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +335 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/index.d.ts +5 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +10 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/rewriter/index.d.ts +45 -0
  14. package/dist/rewriter/index.d.ts.map +1 -0
  15. package/dist/rewriter/index.js +163 -0
  16. package/dist/rewriter/index.js.map +1 -0
  17. package/dist/schema/copy-patterns.d.ts +298 -0
  18. package/dist/schema/copy-patterns.d.ts.map +1 -0
  19. package/dist/schema/copy-patterns.js +53 -0
  20. package/dist/schema/copy-patterns.js.map +1 -0
  21. package/dist/schema/cta-rules.d.ts +274 -0
  22. package/dist/schema/cta-rules.d.ts.map +1 -0
  23. package/dist/schema/cta-rules.js +45 -0
  24. package/dist/schema/cta-rules.js.map +1 -0
  25. package/dist/schema/index.d.ts +2172 -0
  26. package/dist/schema/index.d.ts.map +1 -0
  27. package/dist/schema/index.js +92 -0
  28. package/dist/schema/index.js.map +1 -0
  29. package/dist/schema/tests.d.ts +274 -0
  30. package/dist/schema/tests.d.ts.map +1 -0
  31. package/dist/schema/tests.js +37 -0
  32. package/dist/schema/tests.js.map +1 -0
  33. package/dist/schema/tokens.d.ts +632 -0
  34. package/dist/schema/tokens.d.ts.map +1 -0
  35. package/dist/schema/tokens.js +68 -0
  36. package/dist/schema/tokens.js.map +1 -0
  37. package/dist/schema/voice.d.ts +280 -0
  38. package/dist/schema/voice.d.ts.map +1 -0
  39. package/dist/schema/voice.js +52 -0
  40. package/dist/schema/voice.js.map +1 -0
  41. package/dist/server/billing.d.ts +53 -0
  42. package/dist/server/billing.d.ts.map +1 -0
  43. package/dist/server/billing.js +216 -0
  44. package/dist/server/billing.js.map +1 -0
  45. package/dist/server/http.d.ts +5 -0
  46. package/dist/server/http.d.ts.map +1 -0
  47. package/dist/server/http.js +470 -0
  48. package/dist/server/http.js.map +1 -0
  49. package/dist/server/index.d.ts +3 -0
  50. package/dist/server/index.d.ts.map +1 -0
  51. package/dist/server/index.js +480 -0
  52. package/dist/server/index.js.map +1 -0
  53. package/dist/server/middleware/auth.d.ts +15 -0
  54. package/dist/server/middleware/auth.d.ts.map +1 -0
  55. package/dist/server/middleware/auth.js +83 -0
  56. package/dist/server/middleware/auth.js.map +1 -0
  57. package/dist/utils/pack-loader.d.ts +13 -0
  58. package/dist/utils/pack-loader.d.ts.map +1 -0
  59. package/dist/utils/pack-loader.js +98 -0
  60. package/dist/utils/pack-loader.js.map +1 -0
  61. package/dist/validator/index.d.ts +21 -0
  62. package/dist/validator/index.d.ts.map +1 -0
  63. package/dist/validator/index.js +60 -0
  64. package/dist/validator/index.js.map +1 -0
  65. package/dist/validator/rules/constraints.d.ts +8 -0
  66. package/dist/validator/rules/constraints.d.ts.map +1 -0
  67. package/dist/validator/rules/constraints.js +150 -0
  68. package/dist/validator/rules/constraints.js.map +1 -0
  69. package/dist/validator/rules/cta.d.ts +11 -0
  70. package/dist/validator/rules/cta.d.ts.map +1 -0
  71. package/dist/validator/rules/cta.js +113 -0
  72. package/dist/validator/rules/cta.js.map +1 -0
  73. package/dist/validator/rules/voice.d.ts +6 -0
  74. package/dist/validator/rules/voice.d.ts.map +1 -0
  75. package/dist/validator/rules/voice.js +106 -0
  76. package/dist/validator/rules/voice.js.map +1 -0
  77. package/package.json +61 -0
  78. package/packs/saas/copy_patterns.yaml +423 -0
  79. package/packs/saas/cta_rules.yaml +362 -0
  80. package/packs/saas/manifest.yaml +16 -0
  81. package/packs/saas/tests.yaml +305 -0
  82. package/packs/saas/tokens.json +226 -0
  83. package/packs/saas/voice.yaml +232 -0
@@ -0,0 +1,362 @@
1
+ version: "1.0"
2
+ name: "SaaS CTA Rules"
3
+ description: "Call-to-action patterns and guidelines for B2B SaaS"
4
+
5
+ guidelines:
6
+ verbStyle: imperative
7
+ maxWords: 4
8
+ capitalization: sentence
9
+ avoidWords:
10
+ - "Submit"
11
+ - "Click"
12
+ - "Click here"
13
+ - "Press"
14
+ - "Hit"
15
+ - "Go"
16
+ - "OK"
17
+ - "Yes"
18
+ - "No"
19
+ - "Proceed"
20
+ - "Continue" # unless genuinely continuing a process
21
+ - "Please"
22
+ preferWords:
23
+ - "Save"
24
+ - "Create"
25
+ - "Add"
26
+ - "Send"
27
+ - "Share"
28
+ - "Export"
29
+ - "Import"
30
+ - "Download"
31
+ - "Upload"
32
+ - "View"
33
+ - "Open"
34
+ - "Copy"
35
+ - "Delete"
36
+ - "Remove"
37
+ - "Cancel"
38
+ - "Sign up"
39
+ - "Log in"
40
+ - "Log out"
41
+ - "Try"
42
+ - "Start"
43
+ - "Upgrade"
44
+
45
+ categories:
46
+ - name: "Primary Actions"
47
+ description: "Main actions users take"
48
+ ctas:
49
+ - id: cta-save
50
+ text: "Save"
51
+ context: ["forms", "settings", "editing"]
52
+ priority: primary
53
+ action: "persist changes"
54
+ - id: cta-save-changes
55
+ text: "Save changes"
56
+ context: ["forms with unsaved state"]
57
+ priority: primary
58
+ - id: cta-create
59
+ text: "Create"
60
+ context: ["new resource creation"]
61
+ priority: primary
62
+ - id: cta-create-item
63
+ text: "Create {{item}}"
64
+ context: ["specific resource creation"]
65
+ priority: primary
66
+ - id: cta-add
67
+ text: "Add"
68
+ context: ["adding to existing collection"]
69
+ priority: primary
70
+ - id: cta-send
71
+ text: "Send"
72
+ context: ["messages", "emails", "invitations"]
73
+ priority: primary
74
+ - id: cta-share
75
+ text: "Share"
76
+ context: ["sharing resources"]
77
+ priority: primary
78
+
79
+ - name: "Authentication"
80
+ description: "Login and signup flows"
81
+ ctas:
82
+ - id: cta-signup
83
+ text: "Sign up"
84
+ context: ["registration"]
85
+ priority: primary
86
+ - id: cta-signup-free
87
+ text: "Sign up free"
88
+ context: ["free tier registration"]
89
+ priority: primary
90
+ - id: cta-login
91
+ text: "Log in"
92
+ context: ["returning user"]
93
+ priority: primary
94
+ - id: cta-logout
95
+ text: "Log out"
96
+ context: ["session end"]
97
+ priority: secondary
98
+ - id: cta-forgot
99
+ text: "Forgot password?"
100
+ context: ["password recovery"]
101
+ priority: tertiary
102
+ - id: cta-reset
103
+ text: "Reset password"
104
+ context: ["password reset form"]
105
+ priority: primary
106
+
107
+ - name: "Data Actions"
108
+ description: "Importing and exporting data"
109
+ ctas:
110
+ - id: cta-export
111
+ text: "Export"
112
+ context: ["data export"]
113
+ priority: primary
114
+ - id: cta-export-format
115
+ text: "Export as {{format}}"
116
+ context: ["specific format export"]
117
+ priority: primary
118
+ - id: cta-download
119
+ text: "Download"
120
+ context: ["file download"]
121
+ priority: primary
122
+ - id: cta-import
123
+ text: "Import"
124
+ context: ["data import"]
125
+ priority: primary
126
+ - id: cta-upload
127
+ text: "Upload"
128
+ context: ["file upload"]
129
+ priority: primary
130
+ - id: cta-copy
131
+ text: "Copy"
132
+ context: ["clipboard copy"]
133
+ priority: secondary
134
+ - id: cta-copy-link
135
+ text: "Copy link"
136
+ context: ["sharing via link"]
137
+ priority: secondary
138
+
139
+ - name: "Destructive Actions"
140
+ description: "Irreversible or dangerous actions"
141
+ ctas:
142
+ - id: cta-delete
143
+ text: "Delete"
144
+ context: ["permanent removal"]
145
+ priority: primary
146
+ action: "permanent deletion"
147
+ - id: cta-delete-item
148
+ text: "Delete {{item}}"
149
+ context: ["specific item deletion"]
150
+ priority: primary
151
+ - id: cta-remove
152
+ text: "Remove"
153
+ context: ["removal from collection, reversible"]
154
+ priority: primary
155
+ - id: cta-cancel-action
156
+ text: "Cancel {{item}}"
157
+ context: ["canceling subscription, action"]
158
+ priority: primary
159
+
160
+ - name: "Navigation"
161
+ description: "Moving between views"
162
+ ctas:
163
+ - id: cta-view
164
+ text: "View"
165
+ context: ["viewing details"]
166
+ priority: secondary
167
+ - id: cta-view-all
168
+ text: "View all"
169
+ context: ["seeing full list"]
170
+ priority: secondary
171
+ - id: cta-view-details
172
+ text: "View details"
173
+ context: ["expanded view"]
174
+ priority: secondary
175
+ - id: cta-open
176
+ text: "Open"
177
+ context: ["opening resource"]
178
+ priority: secondary
179
+ - id: cta-back
180
+ text: "Back"
181
+ context: ["returning to previous"]
182
+ priority: tertiary
183
+ - id: cta-learn-more
184
+ text: "Learn more"
185
+ context: ["documentation link"]
186
+ priority: tertiary
187
+
188
+ - name: "Cancellation"
189
+ description: "Canceling or dismissing"
190
+ ctas:
191
+ - id: cta-cancel
192
+ text: "Cancel"
193
+ context: ["dismissing modal", "abandoning action"]
194
+ priority: secondary
195
+ - id: cta-dismiss
196
+ text: "Dismiss"
197
+ context: ["closing notification"]
198
+ priority: tertiary
199
+ - id: cta-close
200
+ text: "Close"
201
+ context: ["closing modal"]
202
+ priority: secondary
203
+ - id: cta-skip
204
+ text: "Skip"
205
+ context: ["optional onboarding"]
206
+ priority: tertiary
207
+ - id: cta-skip-for-now
208
+ text: "Skip for now"
209
+ context: ["optional but recommended step"]
210
+ priority: tertiary
211
+ - id: cta-not-now
212
+ text: "Not now"
213
+ context: ["dismissing soft prompt"]
214
+ priority: tertiary
215
+
216
+ - name: "Conversion"
217
+ description: "Upgrade and billing"
218
+ ctas:
219
+ - id: cta-upgrade
220
+ text: "Upgrade"
221
+ context: ["plan upgrade"]
222
+ priority: primary
223
+ - id: cta-upgrade-plan
224
+ text: "Upgrade plan"
225
+ context: ["explicit plan upgrade"]
226
+ priority: primary
227
+ - id: cta-view-plans
228
+ text: "View plans"
229
+ context: ["pricing comparison"]
230
+ priority: secondary
231
+ - id: cta-start-trial
232
+ text: "Start free trial"
233
+ context: ["trial initiation"]
234
+ priority: primary
235
+ - id: cta-try-free
236
+ text: "Try for free"
237
+ context: ["trial CTA"]
238
+ priority: primary
239
+ - id: cta-get-started
240
+ text: "Get started"
241
+ context: ["onboarding initiation"]
242
+ priority: primary
243
+
244
+ - name: "Communication"
245
+ description: "Reaching out"
246
+ ctas:
247
+ - id: cta-contact
248
+ text: "Contact us"
249
+ context: ["support", "sales"]
250
+ priority: secondary
251
+ - id: cta-contact-support
252
+ text: "Contact support"
253
+ context: ["help request"]
254
+ priority: secondary
255
+ - id: cta-contact-sales
256
+ text: "Contact sales"
257
+ context: ["enterprise inquiry"]
258
+ priority: primary
259
+ - id: cta-send-feedback
260
+ text: "Send feedback"
261
+ context: ["feedback form"]
262
+ priority: secondary
263
+ - id: cta-report-issue
264
+ text: "Report issue"
265
+ context: ["bug report"]
266
+ priority: secondary
267
+
268
+ antiPatterns:
269
+ - pattern: "(?i)^submit$"
270
+ isRegex: true
271
+ reason: "Generic and unclear"
272
+ suggestion: "Use specific action: 'Save', 'Send', 'Create'"
273
+
274
+ - pattern: "(?i)^click here"
275
+ isRegex: true
276
+ reason: "Poor accessibility and unclear"
277
+ suggestion: "Describe the destination or action"
278
+
279
+ - pattern: "(?i)^yes$"
280
+ isRegex: true
281
+ reason: "Doesn't describe the action"
282
+ suggestion: "Use the specific action: 'Delete', 'Confirm', 'Log out'"
283
+
284
+ - pattern: "(?i)^no$"
285
+ isRegex: true
286
+ reason: "Doesn't describe the action"
287
+ suggestion: "Use 'Cancel' or 'Keep {{item}}'"
288
+
289
+ - pattern: "(?i)^ok$"
290
+ isRegex: true
291
+ reason: "Vague confirmation"
292
+ suggestion: "Use the specific action or 'Done'"
293
+
294
+ - pattern: "(?i)^go$"
295
+ isRegex: true
296
+ reason: "Doesn't describe what happens"
297
+ suggestion: "Use specific action: 'Search', 'View', 'Open'"
298
+
299
+ - pattern: "(?i)^proceed"
300
+ isRegex: true
301
+ reason: "Formal and unclear"
302
+ suggestion: "Use specific action"
303
+
304
+ - pattern: "(?i)^continue$"
305
+ isRegex: true
306
+ reason: "Only use when genuinely continuing a multi-step process"
307
+ suggestion: "Use specific action if not in a wizard"
308
+
309
+ - pattern: "(?i)!$"
310
+ isRegex: true
311
+ reason: "CTAs don't need exclamation marks"
312
+ suggestion: "Remove the exclamation mark"
313
+
314
+ - pattern: "(?i)^please "
315
+ isRegex: true
316
+ reason: "CTAs should be direct commands"
317
+ suggestion: "Remove 'please'"
318
+
319
+ - pattern: "(?i)\\bhere\\b"
320
+ isRegex: true
321
+ reason: "'here' is meaningless in CTAs"
322
+ suggestion: "Describe the destination"
323
+
324
+ contextualRules:
325
+ - context: "Destructive action confirmation"
326
+ required: []
327
+ forbidden:
328
+ - "Yes"
329
+ - "OK"
330
+ - "Confirm"
331
+ preferred:
332
+ - "Delete"
333
+ - "Remove"
334
+ - "Cancel {{item}}"
335
+
336
+ - context: "Form submission"
337
+ required: []
338
+ forbidden:
339
+ - "Submit"
340
+ preferred:
341
+ - "Save"
342
+ - "Create"
343
+ - "Send"
344
+ - "Add"
345
+
346
+ - context: "Modal dismissal"
347
+ required: []
348
+ forbidden:
349
+ - "X" # as text, icon is fine
350
+ preferred:
351
+ - "Cancel"
352
+ - "Close"
353
+ - "Done"
354
+
355
+ - context: "Onboarding skip"
356
+ required: []
357
+ forbidden:
358
+ - "No thanks"
359
+ preferred:
360
+ - "Skip"
361
+ - "Skip for now"
362
+ - "Set up later"
@@ -0,0 +1,16 @@
1
+ name: saas
2
+ version: "1.0.0"
3
+ description: "Default style pack for B2B SaaS products. Professional, clear, helpful."
4
+ author: StyleMCP
5
+ license: MIT
6
+
7
+ files:
8
+ voice: voice.yaml
9
+ copyPatterns: copy_patterns.yaml
10
+ ctaRules: cta_rules.yaml
11
+ tokens: tokens.json
12
+ tests: tests.yaml
13
+
14
+ config:
15
+ strictMode: false
16
+ minScore: 70
@@ -0,0 +1,305 @@
1
+ version: "1.0"
2
+ name: "SaaS Pack Tests"
3
+ description: "Test cases for the SaaS style pack"
4
+
5
+ config:
6
+ stopOnFirstFailure: false
7
+ verbose: true
8
+
9
+ tests:
10
+ # SHOULD PASS
11
+ - id: pass-simple-success
12
+ name: "Simple success message"
13
+ input: "Project created."
14
+ expect:
15
+ pass: true
16
+ minScore: 90
17
+ tags: ["success", "simple"]
18
+
19
+ - id: pass-error-with-solution
20
+ name: "Error with specific solution"
21
+ input: "We couldn't process your payment. Your card was declined. Try a different card or contact your bank."
22
+ expect:
23
+ pass: true
24
+ minScore: 80
25
+ tags: ["error", "actionable"]
26
+
27
+ - id: pass-clear-cta
28
+ name: "Clear descriptive CTA"
29
+ input: "View your dashboard"
30
+ expect:
31
+ pass: true
32
+ minScore: 95
33
+ tags: ["cta"]
34
+
35
+ - id: pass-specific-empty-state
36
+ name: "Empty state with clear action"
37
+ input: "No projects yet. Create one to start tracking your work."
38
+ expect:
39
+ pass: true
40
+ minScore: 85
41
+ tags: ["empty-state"]
42
+
43
+ - id: pass-concrete-claim
44
+ name: "Concrete claim without jargon"
45
+ input: "Our search returns results in under 100ms."
46
+ expect:
47
+ pass: true
48
+ minScore: 85
49
+ tags: ["marketing"]
50
+
51
+ - id: pass-form-validation
52
+ name: "Helpful form validation"
53
+ input: "Password must be at least 8 characters. You have 6."
54
+ expect:
55
+ pass: true
56
+ minScore: 90
57
+ tags: ["validation"]
58
+
59
+ - id: pass-destructive-confirmation
60
+ name: "Clear destructive confirmation"
61
+ input: "Delete this project? You'll lose all 47 tasks and 12 files."
62
+ expect:
63
+ pass: true
64
+ minScore: 85
65
+ tags: ["confirmation", "destructive"]
66
+
67
+ # SHOULD FAIL - Forbidden phrases
68
+ - id: fail-revolutionary
69
+ name: "Uses forbidden 'revolutionary'"
70
+ input: "Our revolutionary new feature will transform your workflow."
71
+ expect:
72
+ pass: false
73
+ maxScore: 60
74
+ violations:
75
+ - rule: vocabulary.forbidden
76
+ severity: error
77
+ tags: ["forbidden", "marketing-speak"]
78
+
79
+ - id: fail-synergy
80
+ name: "Uses forbidden 'synergy'"
81
+ input: "We leverage synergies to maximize value for stakeholders."
82
+ expect:
83
+ pass: false
84
+ violations:
85
+ - rule: vocabulary.forbidden
86
+ tags: ["forbidden", "jargon"]
87
+
88
+ - id: fail-cutting-edge
89
+ name: "Uses forbidden 'cutting-edge'"
90
+ input: "Built with cutting-edge technology."
91
+ expect:
92
+ pass: false
93
+ violations:
94
+ - rule: vocabulary.forbidden
95
+ tags: ["forbidden"]
96
+
97
+ # SHOULD FAIL - doNot patterns
98
+ - id: fail-click-here
99
+ name: "Uses 'click here'"
100
+ input: "Click here to learn more about our features."
101
+ expect:
102
+ pass: false
103
+ violations:
104
+ - rule: doNot.click-here
105
+ severity: error
106
+ tags: ["accessibility", "cta"]
107
+
108
+ - id: fail-sorry-inconvenience
109
+ name: "Uses corporate non-apology"
110
+ input: "We're sorry for any inconvenience this may have caused."
111
+ expect:
112
+ pass: false
113
+ violations:
114
+ - rule: doNot.corporate-apology
115
+ severity: error
116
+ tags: ["error", "apology"]
117
+
118
+ - id: fail-simply
119
+ name: "Uses dismissive 'simply'"
120
+ input: "Simply configure your settings and you're done."
121
+ expect:
122
+ pass: false
123
+ violations:
124
+ - rule: doNot.dismissive-adverbs
125
+ severity: warning
126
+ tags: ["dismissive"]
127
+
128
+ - id: fail-obviously
129
+ name: "Uses dismissive 'obviously'"
130
+ input: "Obviously, you'll want to set up your profile first."
131
+ expect:
132
+ pass: false
133
+ violations:
134
+ - rule: doNot.dismissive-adverbs
135
+ tags: ["dismissive"]
136
+
137
+ - id: fail-dont-hesitate
138
+ name: "Uses 'don't hesitate'"
139
+ input: "Please don't hesitate to reach out if you have questions."
140
+ expect:
141
+ pass: false
142
+ violations:
143
+ - rule: doNot.hesitation
144
+ tags: ["filler"]
145
+
146
+ - id: fail-intensifiers
147
+ name: "Uses weak intensifiers"
148
+ input: "We're really excited to announce this incredibly amazing feature."
149
+ expect:
150
+ pass: false
151
+ violations:
152
+ - rule: doNot.intensifiers
153
+ tags: ["intensifiers"]
154
+
155
+ # SHOULD FAIL - Vocabulary rules
156
+ - id: fail-utilize
157
+ name: "Uses 'utilize' instead of 'use'"
158
+ input: "Utilize our API to build integrations."
159
+ expect:
160
+ pass: false
161
+ violations:
162
+ - rule: vocabulary.preferred
163
+ tags: ["vocabulary"]
164
+
165
+ - id: fail-leverage
166
+ name: "Uses 'leverage' as verb"
167
+ input: "Leverage our platform to grow your business."
168
+ expect:
169
+ pass: false
170
+ violations:
171
+ - rule: vocabulary.forbidden
172
+ tags: ["vocabulary", "jargon"]
173
+
174
+ - id: fail-facilitate
175
+ name: "Uses 'facilitate' instead of 'help'"
176
+ input: "Our tool facilitates team collaboration."
177
+ expect:
178
+ pass: false
179
+ violations:
180
+ - rule: vocabulary.preferred
181
+ tags: ["vocabulary"]
182
+
183
+ # SHOULD FAIL - Bad patterns
184
+ - id: fail-vague-error
185
+ name: "Vague error message"
186
+ input: "An error occurred."
187
+ expect:
188
+ pass: false
189
+ maxScore: 50
190
+ tags: ["error", "vague"]
191
+
192
+ - id: fail-generic-success
193
+ name: "Generic success with exclamation"
194
+ input: "Success!"
195
+ expect:
196
+ pass: false
197
+ violations:
198
+ - rule: doNot.exclamation
199
+ tags: ["success", "exclamation"]
200
+
201
+ - id: fail-excited-announcement
202
+ name: "Over-excited announcement"
203
+ input: "We're excited to announce our amazing new feature!"
204
+ expect:
205
+ pass: false
206
+ tags: ["marketing", "exclamation", "intensifiers"]
207
+
208
+ - id: fail-oops
209
+ name: "Informal error with emoji"
210
+ input: "Oops! Something went wrong 😅"
211
+ expect:
212
+ pass: false
213
+ maxScore: 40
214
+ tags: ["error", "informal"]
215
+
216
+ - id: fail-empty-nothing
217
+ name: "Unhelpful empty state"
218
+ input: "Nothing to see here!"
219
+ expect:
220
+ pass: false
221
+ tags: ["empty-state", "exclamation"]
222
+
223
+ - id: fail-invalid-input
224
+ name: "Unhelpful validation"
225
+ input: "Invalid input."
226
+ expect:
227
+ pass: false
228
+ maxScore: 50
229
+ tags: ["validation", "vague"]
230
+
231
+ - id: fail-are-you-sure
232
+ name: "Vague confirmation dialog"
233
+ input: "Are you sure?"
234
+ expect:
235
+ pass: false
236
+ maxScore: 60
237
+ tags: ["confirmation", "vague"]
238
+
239
+ # CTA failures
240
+ - id: fail-cta-submit
241
+ name: "Generic submit CTA"
242
+ input: "Submit"
243
+ expect:
244
+ pass: false
245
+ violations:
246
+ - rule: cta.antiPattern
247
+ tags: ["cta"]
248
+ context:
249
+ type: ui-copy
250
+ component: button
251
+
252
+ - id: fail-cta-yes
253
+ name: "Yes as confirmation CTA"
254
+ input: "Yes"
255
+ expect:
256
+ pass: false
257
+ violations:
258
+ - rule: cta.antiPattern
259
+ tags: ["cta", "confirmation"]
260
+ context:
261
+ component: button
262
+
263
+ - id: fail-cta-exclamation
264
+ name: "CTA with exclamation"
265
+ input: "Get started!"
266
+ expect:
267
+ pass: false
268
+ violations:
269
+ - rule: cta.antiPattern
270
+ tags: ["cta", "exclamation"]
271
+
272
+ # Constraint failures
273
+ - id: fail-long-sentence
274
+ name: "Sentence exceeds max length"
275
+ input: "This is an extremely long sentence that goes on and on and contains way too many words for any reasonable person to read and understand in a single breath without losing track of what the original point was supposed to be in the first place."
276
+ expect:
277
+ pass: false
278
+ violations:
279
+ - rule: constraints.maxSentenceLength
280
+ tags: ["constraints", "length"]
281
+
282
+ # Edge cases
283
+ - id: pass-technical-term
284
+ name: "Technical term is acceptable"
285
+ input: "Configure your API key in Settings."
286
+ expect:
287
+ pass: true
288
+ minScore: 80
289
+ tags: ["technical"]
290
+
291
+ - id: pass-contraction
292
+ name: "Contractions are allowed"
293
+ input: "You'll receive an email when it's ready."
294
+ expect:
295
+ pass: true
296
+ minScore: 85
297
+ tags: ["contractions"]
298
+
299
+ - id: pass-first-plural
300
+ name: "First person plural is preferred"
301
+ input: "We couldn't find that page. Here's what you can do."
302
+ expect:
303
+ pass: true
304
+ minScore: 80
305
+ tags: ["pov"]