@contentrain/rules 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.
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/context/context-bridge.md +241 -0
- package/context/templates/astro.context.json +74 -0
- package/context/templates/next.context.json +74 -0
- package/context/templates/nuxt.context.json +74 -0
- package/context/templates/sveltekit.context.json +74 -0
- package/dist/index.cjs +98 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +27 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +92 -0
- package/dist/index.mjs.map +1 -0
- package/ide/claude-code/contentrain.md +2984 -0
- package/ide/cursor/contentrain.cursorrules +2959 -0
- package/ide/generic/contentrain.md +2984 -0
- package/ide/windsurf/contentrain.windsurfrules +2984 -0
- package/package.json +61 -0
- package/prompts/common.md +81 -0
- package/prompts/generate-mode.md +195 -0
- package/prompts/normalize-mode.md +360 -0
- package/prompts/review-mode.md +241 -0
- package/shared/accessibility-rules.md +155 -0
- package/shared/content-conventions.md +314 -0
- package/shared/content-quality.md +294 -0
- package/shared/i18n-quality.md +293 -0
- package/shared/mcp-usage.md +405 -0
- package/shared/media-rules.md +165 -0
- package/shared/normalize-rules.md +312 -0
- package/shared/schema-rules.md +380 -0
- package/shared/security-rules.md +141 -0
- package/shared/seo-rules.md +224 -0
- package/shared/workflow-rules.md +262 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# Review Mode — Review Pending Content Changes
|
|
2
|
+
|
|
3
|
+
> **Prerequisites:** Read `prompts/common.md` first. All shared rules apply.
|
|
4
|
+
|
|
5
|
+
This mode is for reviewing content changes on pending `contentrain/*` branches before they are merged. You act as a content quality reviewer, applying all Contentrain rules systematically.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Pipeline
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
Step 1: List open contentrain/* branches
|
|
13
|
+
Step 2: Show diffs for selected branch
|
|
14
|
+
Step 3: Apply review checklist
|
|
15
|
+
Step 4: Recommend action
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Step 1: List Pending Branches
|
|
21
|
+
|
|
22
|
+
Call `contentrain_status` to see pending changes and open branches. Identify branches with the `contentrain/` prefix that are awaiting review.
|
|
23
|
+
|
|
24
|
+
Branch naming convention:
|
|
25
|
+
```
|
|
26
|
+
contentrain/{operation}/{model}/{locale}/{timestamp}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Common branch types:
|
|
30
|
+
- `contentrain/content/...` — content updates
|
|
31
|
+
- `contentrain/model/...` — model changes
|
|
32
|
+
- `contentrain/normalize/extract/...` — normalize extraction
|
|
33
|
+
- `contentrain/normalize/reuse/...` — normalize reuse (source patching)
|
|
34
|
+
- `contentrain/new/scaffold-...` — scaffold operations
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Step 2: Show Diffs
|
|
39
|
+
|
|
40
|
+
Examine the changes on the selected branch. Focus on:
|
|
41
|
+
|
|
42
|
+
- New or modified files in `.contentrain/content/`
|
|
43
|
+
- New or modified files in `.contentrain/models/`
|
|
44
|
+
- Modified source files (for reuse branches)
|
|
45
|
+
- Changes to `.contentrain/context.json`
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 3: Apply Review Checklist
|
|
50
|
+
|
|
51
|
+
Evaluate every change against the following categories. Each check has a severity level.
|
|
52
|
+
|
|
53
|
+
### 3.1 Schema Compliance (severity: error)
|
|
54
|
+
|
|
55
|
+
- All required fields present and populated with non-empty values
|
|
56
|
+
- Field values match their declared type (string is string, number is number, etc.)
|
|
57
|
+
- Field values satisfy constraints: `min`, `max`, `pattern`, `options`
|
|
58
|
+
- `unique` fields have no duplicates within the model
|
|
59
|
+
- Relation fields reference existing entries in the target model
|
|
60
|
+
- Dictionary entries are flat key-value pairs (all values are strings)
|
|
61
|
+
- Object-map entries use 12-char hex IDs as keys (collections)
|
|
62
|
+
- Model definitions use valid kinds: `singleton`, `collection`, `document`, `dictionary`
|
|
63
|
+
|
|
64
|
+
### 3.2 Content Quality (severity: warning)
|
|
65
|
+
|
|
66
|
+
Reference: `rules/shared/content-quality.md`
|
|
67
|
+
|
|
68
|
+
- Title length: 50-60 characters
|
|
69
|
+
- Excerpt/description: 120-160 characters, complete sentence, ends with period
|
|
70
|
+
- No placeholder text: no "Lorem ipsum", "TODO", "TBD", "[insert here]", "Sample text"
|
|
71
|
+
- No duplicate content across entries (titles, descriptions, body text)
|
|
72
|
+
- Content follows the correct content type pattern (blog post structure, landing page structure, etc.)
|
|
73
|
+
- Tone matches `context.json > conventions.tone` consistently throughout
|
|
74
|
+
- Vocabulary terms match `vocabulary.json` exactly
|
|
75
|
+
- Active voice preferred over passive voice
|
|
76
|
+
- Heading hierarchy is sequential (H1 > H2 > H3, no skips)
|
|
77
|
+
- Exactly one H1 per page/entry
|
|
78
|
+
|
|
79
|
+
### 3.3 SEO (severity: warning)
|
|
80
|
+
|
|
81
|
+
Reference: `rules/shared/seo-rules.md`
|
|
82
|
+
|
|
83
|
+
- Slug format: lowercase, hyphenated, 3-5 words, no special characters
|
|
84
|
+
- Published slugs have not been changed (breaking change)
|
|
85
|
+
- Slugs are identical across all locales
|
|
86
|
+
- Meta description: 120-155 characters, complete sentence, unique
|
|
87
|
+
- Primary keyword within first 30 characters of title
|
|
88
|
+
- All images have alt text (or explicit empty string for decorative)
|
|
89
|
+
- OG fields populated if model supports them
|
|
90
|
+
|
|
91
|
+
### 3.4 Accessibility (severity: warning)
|
|
92
|
+
|
|
93
|
+
Reference: `rules/shared/accessibility-rules.md`
|
|
94
|
+
|
|
95
|
+
- Link text is descriptive and self-explanatory — no "click here", "read more", "learn more"
|
|
96
|
+
- Heading levels reflect document hierarchy, no skipped levels
|
|
97
|
+
- Alt text describes content and function, not appearance
|
|
98
|
+
- Alt text does not start with "Image of" or "Photo of"
|
|
99
|
+
- Alt text under 125 characters
|
|
100
|
+
- No color-only references to convey meaning
|
|
101
|
+
- Error messages identify the field, describe the error, and explain how to fix it
|
|
102
|
+
- Reading level appropriate for content type (grade 8-10 general, grade 6-8 critical)
|
|
103
|
+
|
|
104
|
+
### 3.5 Security (severity: error)
|
|
105
|
+
|
|
106
|
+
Reference: `rules/shared/security-rules.md`
|
|
107
|
+
|
|
108
|
+
- No `<script>` tags in richtext or markdown fields
|
|
109
|
+
- No `javascript:` protocol in any attribute value
|
|
110
|
+
- No event handler attributes (`onerror`, `onclick`, etc.)
|
|
111
|
+
- No forbidden HTML tags (`<iframe>`, `<embed>`, `<object>`, `<form>`, etc.)
|
|
112
|
+
- No secrets or credentials: API keys, tokens, private keys, connection strings
|
|
113
|
+
- No PII in non-typed fields (emails in non-email fields, phones in non-phone fields)
|
|
114
|
+
- All URLs use `https://` (exception: localhost for development)
|
|
115
|
+
- No path traversal sequences (`../`, `..\\`)
|
|
116
|
+
- No executable file extensions disguised as other types
|
|
117
|
+
|
|
118
|
+
### 3.6 Internationalization (severity: error for completeness, warning for quality)
|
|
119
|
+
|
|
120
|
+
Reference: `rules/shared/i18n-quality.md`
|
|
121
|
+
|
|
122
|
+
- All supported locales have entries for every content item (error if missing)
|
|
123
|
+
- All required fields populated in every locale (error if empty)
|
|
124
|
+
- Translations are idiomatic, not word-for-word literal (warning)
|
|
125
|
+
- Tone preserved across locales (warning)
|
|
126
|
+
- Technical terms follow vocabulary or kept in original form (warning)
|
|
127
|
+
- Brand terms match vocabulary per locale (warning)
|
|
128
|
+
- Translated text fits within field `max` constraints (error)
|
|
129
|
+
- Dictionary keys use semantic dot-notation, always in English (warning)
|
|
130
|
+
- Plural forms use correct CLDR categories for each language (warning)
|
|
131
|
+
|
|
132
|
+
### 3.7 Structural (severity: warning)
|
|
133
|
+
|
|
134
|
+
- JSON files follow canonical serialization: sorted keys, 2-space indent, trailing newline
|
|
135
|
+
- Collection files use object-map format with sorted entry IDs
|
|
136
|
+
- No orphan references (relation targets that do not exist)
|
|
137
|
+
- Model IDs are kebab-case
|
|
138
|
+
- Field keys are snake_case
|
|
139
|
+
- Dictionary keys use dot-notation
|
|
140
|
+
- Naming conventions are consistent with existing content
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Step 4: Recommend Action
|
|
145
|
+
|
|
146
|
+
Based on the review, recommend one of these actions:
|
|
147
|
+
|
|
148
|
+
### Approve
|
|
149
|
+
|
|
150
|
+
All checks pass. No errors, no critical warnings. Content is ready to merge.
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
Recommendation: APPROVE
|
|
154
|
+
- Schema compliance: PASS
|
|
155
|
+
- Content quality: PASS
|
|
156
|
+
- SEO: PASS (or N/A if not public-facing)
|
|
157
|
+
- Accessibility: PASS
|
|
158
|
+
- Security: PASS
|
|
159
|
+
- i18n: PASS (or N/A if single locale)
|
|
160
|
+
- Structural: PASS
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Request Changes
|
|
164
|
+
|
|
165
|
+
No blocking errors, but warnings that should be addressed before merge.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
Recommendation: REQUEST CHANGES
|
|
169
|
+
Findings:
|
|
170
|
+
- [warning] Title "X" is 45 characters, below recommended 50-60 range
|
|
171
|
+
- [warning] Missing alt text on hero image
|
|
172
|
+
- [warning] German translation of "Settings" uses "Konfiguration" instead of vocabulary term "Einstellungen"
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Reject
|
|
176
|
+
|
|
177
|
+
Blocking errors that must be fixed. Content cannot be merged in current state.
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
Recommendation: REJECT
|
|
181
|
+
Findings:
|
|
182
|
+
- [error] Required field "excerpt" is empty in entry "a1b2c3d4e5f6"
|
|
183
|
+
- [error] Relation field "author" references non-existent entry "x9y8z7w6v5u4"
|
|
184
|
+
- [error] Missing locale file: content/blog/blog-post/tr.json
|
|
185
|
+
- [error] XSS pattern detected: <script> tag in richtext field "body"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Severity Levels
|
|
191
|
+
|
|
192
|
+
| Level | Meaning | Action |
|
|
193
|
+
|-------|---------|--------|
|
|
194
|
+
| `error` | Must fix before merge. Content is invalid or unsafe. | REJECT until fixed |
|
|
195
|
+
| `warning` | Should fix. Content is valid but does not meet quality standards. | REQUEST CHANGES or note in approval |
|
|
196
|
+
| `info` | Optional improvement. Content is acceptable but could be better. | Note in approval, do not block |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Review Report Format
|
|
201
|
+
|
|
202
|
+
Structure your review as follows:
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
## Review: [branch-name]
|
|
206
|
+
|
|
207
|
+
### Summary
|
|
208
|
+
[1-2 sentence summary of what this branch changes]
|
|
209
|
+
|
|
210
|
+
### Findings
|
|
211
|
+
|
|
212
|
+
#### Errors (must fix)
|
|
213
|
+
- [error] Description of issue → File: path, Field: name
|
|
214
|
+
|
|
215
|
+
#### Warnings (should fix)
|
|
216
|
+
- [warning] Description of issue → File: path, Field: name
|
|
217
|
+
|
|
218
|
+
#### Info (optional)
|
|
219
|
+
- [info] Suggestion for improvement → File: path, Field: name
|
|
220
|
+
|
|
221
|
+
### Recommendation
|
|
222
|
+
[APPROVE | REQUEST CHANGES | REJECT]
|
|
223
|
+
|
|
224
|
+
### Notes
|
|
225
|
+
[Any additional context, suggestions, or observations]
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Checklist
|
|
231
|
+
|
|
232
|
+
- [ ] All new/modified files examined
|
|
233
|
+
- [ ] Schema compliance verified for every entry
|
|
234
|
+
- [ ] Content quality checked against content-quality.md
|
|
235
|
+
- [ ] SEO rules applied to public-facing content
|
|
236
|
+
- [ ] Accessibility rules checked
|
|
237
|
+
- [ ] Security scan performed (XSS, secrets, PII)
|
|
238
|
+
- [ ] i18n completeness verified (all locales present)
|
|
239
|
+
- [ ] Translation quality assessed (not just present, but correct)
|
|
240
|
+
- [ ] Structural integrity confirmed (canonical JSON, naming conventions)
|
|
241
|
+
- [ ] Clear recommendation provided with specific findings
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Accessibility Rules
|
|
2
|
+
|
|
3
|
+
These rules are MANDATORY for all AI agents creating or editing content in Contentrain projects.
|
|
4
|
+
Violations will be flagged during validation. No exceptions unless explicitly overridden by `context.json` configuration.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Image Accessibility
|
|
9
|
+
|
|
10
|
+
1. Every `image` type field MUST have a corresponding alt text value. If the model defines an `image_alt` field, populate it. If not, include alt text guidance in the image field's `description` metadata.
|
|
11
|
+
|
|
12
|
+
2. Alt text MUST describe the image's **content and function**, not its appearance.
|
|
13
|
+
- GOOD: `"CEO Jane Doe speaking at the 2024 product launch"`
|
|
14
|
+
- BAD: `"A photo with blue tones and a person on stage"`
|
|
15
|
+
|
|
16
|
+
3. Decorative images (visual separators, background textures) MUST have alt text set to an empty string `""`. Never leave alt text undefined or null — explicitly set it to `""`.
|
|
17
|
+
|
|
18
|
+
4. Complex images (charts, infographics, diagrams) MUST have a short alt text summarizing the conclusion, plus a detailed description in an adjacent text field or in the body content.
|
|
19
|
+
- Example alt: `"Bar chart showing Q3 revenue grew 22% year-over-year"`
|
|
20
|
+
- Example adjacent text: full data table or written summary
|
|
21
|
+
|
|
22
|
+
5. Alt text MUST NOT exceed **125 characters**. Screen readers may truncate longer text.
|
|
23
|
+
|
|
24
|
+
6. Icon images used as interactive elements MUST have alt text describing the **action**, not the icon.
|
|
25
|
+
- GOOD: `"Search"`, `"Close menu"`, `"Open settings"`
|
|
26
|
+
- BAD: `"Magnifying glass icon"`, `"X icon"`
|
|
27
|
+
|
|
28
|
+
7. Do not begin alt text with "Image of" or "Photo of" — the screen reader already announces it as an image.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Language & Readability
|
|
33
|
+
|
|
34
|
+
1. Target a **grade 8-10 reading level** (Flesch-Kincaid) for general content.
|
|
35
|
+
|
|
36
|
+
2. Target **grade 6-8** for public-facing critical content: legal notices, safety information, error messages, onboarding flows.
|
|
37
|
+
|
|
38
|
+
3. Use plain language. Prefer common words over formal synonyms:
|
|
39
|
+
- "use" not "utilize"
|
|
40
|
+
- "start" not "commence"
|
|
41
|
+
- "help" not "facilitate"
|
|
42
|
+
- "buy" not "purchase"
|
|
43
|
+
- "end" not "terminate"
|
|
44
|
+
|
|
45
|
+
4. Define every acronym and abbreviation on first use: `"Content Management System (CMS)"`. After the first definition, use the acronym freely.
|
|
46
|
+
|
|
47
|
+
5. Do not use jargon unless the content targets a technical audience. Check `context.json > tone` to determine the audience. When `tone` is `"technical"`, domain-specific terms are acceptable without definitions.
|
|
48
|
+
|
|
49
|
+
6. Keep sentences short: **15-20 words average**. Break long sentences at natural clause boundaries.
|
|
50
|
+
|
|
51
|
+
7. Keep paragraphs short: **3-5 sentences maximum**. Use line breaks between paragraphs.
|
|
52
|
+
|
|
53
|
+
8. Use active voice. Passive voice is acceptable only when the actor is unknown or irrelevant.
|
|
54
|
+
- GOOD: `"The system saves your changes automatically."`
|
|
55
|
+
- BAD: `"Your changes are saved automatically by the system."`
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Link Text
|
|
60
|
+
|
|
61
|
+
1. Link text MUST be descriptive and self-explanatory. It must make sense **out of context** because screen readers present links in an isolated list.
|
|
62
|
+
- GOOD: `"Download the 2024 Annual Report"`
|
|
63
|
+
- BAD: `"Click here"`
|
|
64
|
+
|
|
65
|
+
2. NEVER use these as standalone link text: `"click here"`, `"read more"`, `"learn more"`, `"here"`, `"link"`, `"this"`.
|
|
66
|
+
|
|
67
|
+
3. For file downloads, include the file type and size in the link text:
|
|
68
|
+
- `"Download the Q3 Budget (PDF, 2.4 MB)"`
|
|
69
|
+
|
|
70
|
+
4. Do not use the raw URL as link text unless the content is specifically listing URLs.
|
|
71
|
+
|
|
72
|
+
5. Keep link text concise — describe the destination or action in 2-8 words.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Heading Semantics
|
|
77
|
+
|
|
78
|
+
1. Headings MUST describe the content of their section. Never use headings purely for visual styling (font size, bold).
|
|
79
|
+
|
|
80
|
+
2. Heading levels MUST reflect **document hierarchy**:
|
|
81
|
+
- `h2` for top-level sections within the page
|
|
82
|
+
- `h3` for subsections of an `h2`
|
|
83
|
+
- `h4` for subsections of an `h3`
|
|
84
|
+
- Never skip levels (e.g., `h2` directly to `h4`)
|
|
85
|
+
|
|
86
|
+
3. Every distinct content section SHOULD have a heading.
|
|
87
|
+
|
|
88
|
+
4. Headings MUST NOT be empty or contain only whitespace.
|
|
89
|
+
|
|
90
|
+
5. Do not duplicate heading text within the same page unless sections are genuinely distinct (e.g., "Overview" under two different parent headings is acceptable).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Content Structure
|
|
95
|
+
|
|
96
|
+
1. Use **semantic markup** appropriate to the content type:
|
|
97
|
+
- Unordered lists (`ul`) for items without sequence
|
|
98
|
+
- Ordered lists (`ol`) for steps or ranked items
|
|
99
|
+
- Headings for section titles
|
|
100
|
+
- Paragraphs for body text
|
|
101
|
+
- Blockquotes for quoted material
|
|
102
|
+
|
|
103
|
+
2. Tables MUST include a header row or header column. Keep table structure simple — avoid merged cells and nested tables.
|
|
104
|
+
|
|
105
|
+
3. Provide a text alternative for every piece of non-text content (images, charts, embedded media).
|
|
106
|
+
|
|
107
|
+
4. Sequential content (steps, instructions, timelines) MUST follow logical reading order. Do not rely on CSS or layout to reorder content.
|
|
108
|
+
|
|
109
|
+
5. Lists MUST have at least two items. A single-item list should be rewritten as a paragraph or inline text.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Color & Visual References
|
|
114
|
+
|
|
115
|
+
1. NEVER use color alone to convey meaning.
|
|
116
|
+
- BAD: `"Required fields are highlighted in red."`
|
|
117
|
+
- GOOD: `"Required fields are marked with an asterisk (*)."`
|
|
118
|
+
|
|
119
|
+
2. Do not reference visual position in content text.
|
|
120
|
+
- BAD: `"Click the button on the right."`
|
|
121
|
+
- GOOD: `"Click the Submit button."`
|
|
122
|
+
|
|
123
|
+
3. Ensure all text content is meaningful without any visual context. Content must be understandable when read aloud or rendered in plain text.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Error Messages & Forms
|
|
128
|
+
|
|
129
|
+
1. Error messages MUST identify **which field** has the error.
|
|
130
|
+
|
|
131
|
+
2. Error messages MUST describe **what the error is** and how to fix it.
|
|
132
|
+
- GOOD: `"Enter a valid email address (e.g., name@example.com)."`
|
|
133
|
+
- BAD: `"Invalid input."`
|
|
134
|
+
|
|
135
|
+
3. Use **positive framing** — tell the user what to do, not what they did wrong.
|
|
136
|
+
- GOOD: `"Enter a date in YYYY-MM-DD format."`
|
|
137
|
+
- BAD: `"Wrong date format."`
|
|
138
|
+
|
|
139
|
+
4. Group related form fields with descriptive labels. Every input field MUST have a label.
|
|
140
|
+
|
|
141
|
+
5. Do not use placeholder text as a substitute for labels.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Multimedia
|
|
146
|
+
|
|
147
|
+
1. Video content MUST reference a transcript — either as inline content, a URL, or a relation to a document entry.
|
|
148
|
+
|
|
149
|
+
2. Audio content MUST have a text transcript available.
|
|
150
|
+
|
|
151
|
+
3. If content auto-plays, note this in metadata so the frontend can provide pause/stop controls. Auto-playing media with audio is strongly discouraged.
|
|
152
|
+
|
|
153
|
+
4. Time-based media (video, audio, animations) MUST include duration information when the model supports it.
|
|
154
|
+
|
|
155
|
+
5. Animated content (GIFs, auto-playing videos) should be flagged if longer than 5 seconds — provide a mechanism to pause.
|