@contentrain/rules 0.3.2 → 0.4.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.
@@ -0,0 +1,314 @@
1
+ # Contentrain Content Conventions
2
+
3
+ > These rules govern how content is structured, stored, and serialized in the `.contentrain/` directory. Follow them exactly when creating or modifying content through MCP tools.
4
+
5
+ ---
6
+
7
+ ## 1. Directory Structure
8
+
9
+ All Contentrain data lives under the `.contentrain/` directory at the project root. Understand every subdirectory's purpose before reading or writing.
10
+
11
+ ```
12
+ .contentrain/
13
+ config.json # Project configuration (stack, workflow, locales, domains)
14
+ vocabulary.json # Canonical terms for consistent terminology
15
+ context.json # Project intelligence — committed with content changes, agents READ ONLY
16
+ assets.json # Media asset registry
17
+ models/
18
+ {model-id}.json # Model definitions (one file per model)
19
+ content/
20
+ {domain}/
21
+ {model-id}/
22
+ en.json # Content per locale (i18n: true)
23
+ tr.json
24
+ data.json # Content without locale (i18n: false)
25
+ {slug}/ # Document kind only
26
+ en.md
27
+ tr.md
28
+ meta/
29
+ {model-id}/
30
+ {locale}.json # System-managed metadata
31
+ {slug}/ # Document kind only
32
+ {locale}.json
33
+ client/ # SDK generated client — auto-generated, NEVER edit
34
+ assets/ # Media files (images, videos, documents)
35
+ ```
36
+
37
+ ### Critical Boundaries
38
+
39
+ - **NEVER write to `.contentrain/meta/`** -- metadata is system-managed (status, source, updated_by, approved_by).
40
+ - **NEVER edit `.contentrain/client/`** -- this is auto-generated by `contentrain generate`.
41
+ - **NEVER edit `.contentrain/context.json`** -- MCP writes it; agents read it for project intelligence.
42
+ - **ALWAYS use MCP tools** to create/update content and models. Do not write JSON files directly.
43
+
44
+ ---
45
+
46
+ ## 2. config.json Structure
47
+
48
+ The project configuration file controls global behavior. It is created by `contentrain_init`.
49
+
50
+ ```json
51
+ {
52
+ "version": 1,
53
+ "stack": "nuxt",
54
+ "workflow": "auto-merge",
55
+ "repository": {
56
+ "provider": "github",
57
+ "owner": "contentrain",
58
+ "name": "demo",
59
+ "default_branch": "main"
60
+ },
61
+ "locales": {
62
+ "default": "en",
63
+ "supported": ["en", "tr"]
64
+ },
65
+ "domains": ["blog", "marketing", "system"],
66
+ "assets_path": ".contentrain/assets",
67
+ "branchRetention": 30
68
+ }
69
+ ```
70
+
71
+ ### Field Reference
72
+
73
+ | Field | Type | Description |
74
+ |-------|------|-------------|
75
+ | `version` | `number` | Config schema version. Always `1`. |
76
+ | `stack` | `string` | Detected or set framework: `"nuxt"`, `"next"`, `"astro"`, `"sveltekit"`, `"react"`, `"node"` |
77
+ | `workflow` | `string` | `"auto-merge"` (solo dev) or `"review"` (team governance) |
78
+ | `repository` | `object` | Git remote info. Provider is always `"github"` in v1. |
79
+ | `locales.default` | `string` | Primary locale (ISO 639-1) |
80
+ | `locales.supported` | `string[]` | All locales including default |
81
+ | `domains` | `string[]` | Organizational groups for content (e.g., `"blog"`, `"marketing"`, `"system"`) |
82
+ | `assets_path` | `string` | Path for media files |
83
+ | `branchRetention` | `number` | Days to keep merged branches |
84
+
85
+ ---
86
+
87
+ ## 3. Content File Formats by Model Kind
88
+
89
+ Each of the 4 model kinds has a distinct storage format. Know them precisely.
90
+
91
+ ### 3.1 Singleton
92
+
93
+ One JSON object per locale file. No `id` field.
94
+
95
+ **Path:** `.contentrain/content/{domain}/{model-id}/{locale}.json`
96
+
97
+ ```json
98
+ {
99
+ "cta": "Get Started",
100
+ "subtitle": "The modern content platform",
101
+ "title": "Build faster"
102
+ }
103
+ ```
104
+
105
+ **Use for:** Hero sections, navigation, site config, form labels -- anything with exactly one instance per locale.
106
+
107
+ ### 3.2 Collection
108
+
109
+ Object-map on disk: keys are entry IDs, sorted lexicographically. The `id` field is the key itself and is NOT stored inside the entry object.
110
+
111
+ **Path:** `.contentrain/content/{domain}/{model-id}/{locale}.json`
112
+
113
+ ```json
114
+ {
115
+ "a1b2c3d4e5f6": {
116
+ "avatar": "assets/ahmet.jpg",
117
+ "name": "Ahmet",
118
+ "role": "CEO"
119
+ },
120
+ "f6e5d4c3b2a1": {
121
+ "avatar": "assets/jane.jpg",
122
+ "name": "Jane",
123
+ "role": "CTO"
124
+ }
125
+ }
126
+ ```
127
+
128
+ **MCP output format differs from storage:** MCP tools return collections as arrays with `id` injected:
129
+
130
+ ```json
131
+ [
132
+ { "id": "a1b2c3d4e5f6", "name": "Ahmet", "role": "CEO", "avatar": "assets/ahmet.jpg" },
133
+ { "id": "f6e5d4c3b2a1", "name": "Jane", "role": "CTO", "avatar": "assets/jane.jpg" }
134
+ ]
135
+ ```
136
+
137
+ **Why object-map?**
138
+ - Sorted keys produce predictable diffs and minimize Git merge conflicts.
139
+ - No ID duplication -- key IS the ID.
140
+ - Consistent structure with metadata files.
141
+
142
+ ### 3.3 Document
143
+
144
+ Markdown file with YAML-like frontmatter. One file per slug per locale.
145
+
146
+ **Path:** `.contentrain/content/{domain}/{model-id}/{slug}/{locale}.md`
147
+
148
+ ```markdown
149
+ ---
150
+ title: Getting Started
151
+ slug: getting-started
152
+ author: a1b2c3d4e5f6
153
+ tags: [tutorial, intro]
154
+ ---
155
+ # Getting Started with Contentrain
156
+
157
+ Your markdown body content here...
158
+ ```
159
+
160
+ **Use for:** Blog posts, documentation pages, changelogs -- long-form content with typed metadata.
161
+
162
+ ### 3.4 Dictionary
163
+
164
+ Flat key-value JSON per locale. No `fields` in the model definition -- all values are strings.
165
+
166
+ **Path:** `.contentrain/content/{domain}/{model-id}/{locale}.json`
167
+
168
+ ```json
169
+ {
170
+ "auth.expired": "Session expired",
171
+ "auth.failed": "Authentication failed",
172
+ "validation.required": "{field} is required"
173
+ }
174
+ ```
175
+
176
+ **Use for:** Error messages, UI strings, i18n translation files, mobile app strings.
177
+
178
+ ---
179
+
180
+ ## 4. Canonical Serialization Rules
181
+
182
+ ALL JSON files in `.contentrain/` MUST follow these rules for deterministic, git-friendly output:
183
+
184
+ 1. **Keys sorted lexicographically** within every object (including nested objects).
185
+ 2. **2-space indent** for all nesting levels.
186
+ 3. **UTF-8 encoding** without BOM.
187
+ 4. **Trailing newline** at end of file (single `\n` after closing brace/bracket).
188
+ 5. **Omit null values** -- do not write `"field": null`.
189
+ 6. **Omit default values** -- if `required` is `false`, do not include it. If `default` is `null`, do not include it.
190
+ 7. **Field key order in content entries** follows the model definition insertion order for readability, but storage uses lexicographic sort for determinism.
191
+
192
+ ### Why This Matters
193
+
194
+ - Deterministic output means identical data always produces identical files.
195
+ - Sorted keys prevent artificial Git diffs from key reordering.
196
+ - Clean diffs enable meaningful code review of content changes.
197
+
198
+ ---
199
+
200
+ ## 5. System Fields
201
+
202
+ Several fields are managed by the platform. Agents MUST NOT set or modify them.
203
+
204
+ | Field | Where | Managed By |
205
+ |-------|-------|------------|
206
+ | `id` | Collection entry key | Auto-generated 12-char hex UUID |
207
+ | `slug` | Document directory name | Derived from content or set by agent via `slug` field |
208
+ | `createdAt` | Not stored | Derived from Git commit history |
209
+ | `updatedAt` | Not stored | Derived from Git commit history |
210
+ | `status` | `.contentrain/meta/` | Platform workflow engine |
211
+ | `source` | `.contentrain/meta/` | Set by MCP: `"agent"`, `"human"`, or `"import"` |
212
+ | `updated_by` | `.contentrain/meta/` | Set by MCP: agent name or user email |
213
+ | `approved_by` | `.contentrain/meta/` | Set by Studio on review approval |
214
+
215
+ **Rule:** When creating content via `contentrain_content_save`, provide only the content fields defined in the model. Do not include `id`, `createdAt`, `updatedAt`, `status`, or any metadata fields.
216
+
217
+ ---
218
+
219
+ ## 6. Localization Rules
220
+
221
+ | Rule | Detail |
222
+ |------|--------|
223
+ | `i18n: true` on model | Each locale gets its own file: `en.json`, `tr.json`, etc. |
224
+ | `i18n: false` on model | Single file: `data.json` (or `{slug}.md` for documents) |
225
+ | Locale code | ISO 639-1: `en`, `tr`, `de`, `fr`, `ja`, `ar` |
226
+ | ID/slug are locale-agnostic | The same entry ID or document slug is used across all locales |
227
+ | Entry parity (collections) | All locales MUST have the same set of entry IDs |
228
+ | Key parity (dictionaries) | All locales MUST have the same set of keys |
229
+
230
+ ### Validation Checks
231
+
232
+ | Check | Severity | Example |
233
+ |-------|----------|---------|
234
+ | Missing locale file | Error | `hero: tr.json missing` |
235
+ | Collection entry ID mismatch | Error | `team-members: entry "member-2" missing in tr` |
236
+ | Dictionary key missing | Warning | `error-messages: tr missing 5 keys` |
237
+ | Document missing translation | Warning | `blog-post: "getting-started" has no tr translation` |
238
+
239
+ ---
240
+
241
+ ## 7. Vocabulary
242
+
243
+ The `vocabulary.json` file provides canonical terms for consistent content.
244
+
245
+ ```json
246
+ {
247
+ "version": 1,
248
+ "terms": {
249
+ "email": { "en": "Email", "tr": "E-posta" },
250
+ "sign-up": { "en": "Sign Up", "tr": "Kayit Ol" }
251
+ }
252
+ }
253
+ ```
254
+
255
+ ### Rules
256
+
257
+ - **Check vocabulary FIRST** before writing any content. Use existing terms when they match.
258
+ - **Add new terms** to the vocabulary when creating content with reusable terminology.
259
+ - **Term keys** are kebab-case identifiers.
260
+ - **Each term** maps to locale-specific approved strings.
261
+ - Vocabulary ensures consistency across models, locales, and agent sessions.
262
+
263
+ ---
264
+
265
+ ## 8. context.json
266
+
267
+ MCP writes `context.json` after every write operation. It provides project intelligence for agents and Studio synchronization.
268
+
269
+ ```json
270
+ {
271
+ "version": "1.0",
272
+ "lastOperation": {
273
+ "tool": "content_save",
274
+ "model": "blog-post",
275
+ "locale": "en",
276
+ "entries": ["a1b2c3d4e5f6"],
277
+ "timestamp": "2026-03-11T14:30:00Z",
278
+ "source": "mcp-local"
279
+ },
280
+ "stats": {
281
+ "models": 5,
282
+ "entries": 142,
283
+ "locales": ["en", "tr"],
284
+ "lastSync": "2026-03-11T14:30:00Z"
285
+ }
286
+ }
287
+ ```
288
+
289
+ ### Rules
290
+
291
+ - **Read only** -- agents MUST NOT write to this file.
292
+ - **Use it for awareness** -- check last operation, entry counts, locale coverage.
293
+ - `source` values: `"mcp-local"` (IDE), `"mcp-studio"` (Studio server-side), `"studio-ui"` (Studio direct).
294
+ - Updated only on write operations (not reads).
295
+ - Git-tracked within `.contentrain/`.
296
+
297
+ ---
298
+
299
+ ## 9. Assets
300
+
301
+ Media files are stored in the configured `assets_path`. The `assets.json` file tracks registered assets.
302
+
303
+ ```json
304
+ [
305
+ { "path": "assets/hero.webp", "type": "image/webp", "size": 245680, "alt": "Hero background" }
306
+ ]
307
+ ```
308
+
309
+ ### Rules for Media References
310
+
311
+ - Use relative paths from the `.contentrain/` root in content fields.
312
+ - Media field types (`image`, `video`, `file`) store string path references.
313
+ - In v1, media fields are URL/path strings only. Upload and processing are out of scope.
314
+ - Always provide `alt` text for images when the information is available.
@@ -0,0 +1,294 @@
1
+ # Content Quality Rules
2
+
3
+ These rules govern how AI agents create and edit content in Contentrain projects.
4
+ Every rule is mandatory. Violations must be fixed before committing.
5
+
6
+ ---
7
+
8
+ ## 1. Writing Structure
9
+
10
+ ### 1.1 Heading Hierarchy
11
+
12
+ - Use exactly ONE H1 per page. The H1 is the page/entry title.
13
+ - Follow sequential order: H1 → H2 → H3 → H4 → H5 → H6.
14
+ - NEVER skip levels. An H4 must be preceded by an H3 in the same section.
15
+ - Do not use headings for visual styling. A heading implies a content section.
16
+
17
+ ### 1.2 Titles
18
+
19
+ - Length: 50-60 characters. Measure before committing.
20
+ - Place the primary keyword within the first 30 characters.
21
+ - Use action-oriented phrasing: "Build a REST API" not "REST API Overview".
22
+ - No clickbait: "You Won't Believe..." is forbidden.
23
+ - No ALL CAPS titles. Use sentence case or title case per project convention.
24
+ - Every title must be unique within its collection.
25
+
26
+ ### 1.3 Excerpts and Descriptions
27
+
28
+ - Length: 120-160 characters. Must be a complete sentence.
29
+ - Summarize the VALUE the reader gets, not the process of writing.
30
+ - GOOD: "Learn how to deploy a Node.js app to production in under 5 minutes."
31
+ - BAD: "This article discusses deployment."
32
+ - End with a period. No trailing ellipsis.
33
+ - Must differ from the title — do not repeat the title verbatim.
34
+
35
+ ### 1.4 Body Content
36
+
37
+ - Prefer active voice. Passive voice is acceptable only when the actor is unknown or irrelevant.
38
+ - Target reading grade 8-10 (Flesch-Kincaid). Avoid unnecessarily complex sentences.
39
+ - Paragraphs: 3-5 sentences each. Break longer paragraphs.
40
+ - Use transition sentences between sections to maintain flow.
41
+ - Front-load key information — most important point first in each paragraph.
42
+ - One idea per paragraph. Do not combine unrelated points.
43
+
44
+ ### 1.5 Lists
45
+
46
+ - Use parallel grammatical structure across all items.
47
+ - GOOD: "Install dependencies", "Configure the server", "Run the tests"
48
+ - BAD: "Install dependencies", "Server configuration", "You should run tests"
49
+ - Punctuation: if items are complete sentences, end each with a period. If fragments, no terminal punctuation. Be consistent within a single list.
50
+ - Ordered lists for sequential steps. Unordered lists for non-sequential items.
51
+ - Minimum 2 items in any list. A single-item list is not a list.
52
+
53
+ ### 1.6 No Placeholder Text
54
+
55
+ Reject and replace any of the following immediately:
56
+
57
+ - "Lorem ipsum" or any Latin filler text
58
+ - "TODO", "TBD", "FIXME", "XXX" in content fields
59
+ - "[insert here]", "[your text]", "[placeholder]"
60
+ - "Sample text", "Example content", "Test entry"
61
+ - Empty strings in required fields
62
+
63
+ If the agent cannot produce real content, it must leave the entry in `draft` status and flag the field explicitly. Never commit placeholder text.
64
+
65
+ ### 1.7 No Duplicate Content
66
+
67
+ - The same text block must not appear in multiple entries within a collection.
68
+ - Titles must be unique across all entries in the same collection.
69
+ - Descriptions/excerpts must be unique across all entries in the same collection.
70
+ - If content is shared across entries, extract it to a referenced entry and use a `relation` field.
71
+ - Before writing, query existing entries to confirm no duplication.
72
+
73
+ ---
74
+
75
+ ## 2. Tone and Voice
76
+
77
+ ### 2.1 Project Tone Configuration
78
+
79
+ - Read `.contentrain/context.json` → `conventions.tone` before writing any content.
80
+ - If the field exists, match the specified tone exactly.
81
+ - If `context.json` does not exist or `conventions.tone` is absent, default to **neutral professional** tone.
82
+ - Never override or ignore the configured tone.
83
+
84
+ ### 2.2 Vocabulary Compliance
85
+
86
+ - Read `.contentrain/vocabulary.json` before writing content.
87
+ - Use canonical terms exactly as defined. Never invent synonyms for canonical terms.
88
+ - If vocabulary defines "Sign up", do not write "Register", "Create account", or "Join".
89
+ - Respect `brand_terms`: use exact casing and spacing as defined.
90
+ - If brand defines "GitHub", never write "Github", "github", or "GH".
91
+ - Respect `forbidden_terms`: never use any term on this list.
92
+ - If `vocabulary.json` does not exist, proceed without term constraints but maintain internal consistency — pick one term and use it everywhere.
93
+
94
+ ### 2.3 Content Type Voice Mapping
95
+
96
+ Match voice to content type:
97
+
98
+ | Content Type | Voice | Characteristics |
99
+ |---|---|---|
100
+ | Marketing / Landing pages | Persuasive | Benefit-focused, confident, action-oriented, second person ("you") |
101
+ | Documentation / Guides | Instructional | Step-by-step, precise, imperative mood ("Run the command"), third person for concepts |
102
+ | Error messages | Empathetic | Solution-oriented, no blame, explain what happened and what to do next |
103
+ | UI labels | Concise | Consistent terminology, sentence case, no articles unless needed for clarity |
104
+ | Blog posts | Conversational-professional | Engaging, informative, first person plural ("we") acceptable |
105
+ | Changelogs | Factual | Past tense, specific, version-referenced, no marketing language |
106
+
107
+ ### 2.4 Consistency Within an Entry
108
+
109
+ - Do not shift tone mid-entry. If the opening is formal, maintain formality throughout.
110
+ - Do not mix second person ("you") and third person ("the user") within the same entry.
111
+ - Maintain consistent use of contractions: either use them throughout or not at all per project tone.
112
+
113
+ ---
114
+
115
+ ## 3. Content Type Patterns
116
+
117
+ ### 3.1 Blog Post (document kind)
118
+
119
+ Required structure:
120
+
121
+ 1. **Hook opening** (1-2 sentences): State the problem, ask a question, or present a surprising fact.
122
+ 2. **Context** (1 paragraph): Why this topic matters now.
123
+ 3. **Scannable body**: Use H2/H3 subheadings every 2-4 paragraphs. Each section is self-contained.
124
+ 4. **Conclusion** (1 paragraph): Summarize key takeaways.
125
+ 5. **Call-to-action**: Direct the reader to a next step (related post, product, signup).
126
+
127
+ Do not start with "In this article, we will discuss..." — start with value.
128
+
129
+ ### 3.2 Landing Page (singleton kind)
130
+
131
+ Required sections in order:
132
+
133
+ 1. **Hero statement**: One sentence, max 10 words. State the core value proposition.
134
+ 2. **Problem**: 2-3 sentences describing the pain point.
135
+ 3. **Solution**: How the product/service solves it. Benefit-focused, not feature-focused.
136
+ 4. **Features**: 3-6 features, each with a heading and 1-2 sentence description.
137
+ 5. **Social proof**: Testimonials, logos, statistics. Must reference real data.
138
+ 6. **CTA**: Clear, single action. Use action verbs: "Start free trial", "Get started", "Book a demo".
139
+
140
+ ### 3.3 Documentation (document kind)
141
+
142
+ Required structure:
143
+
144
+ 1. **Prerequisites callout**: List what the reader needs before starting (tools, accounts, knowledge).
145
+ 2. **Overview** (1-2 sentences): What the reader will accomplish.
146
+ 3. **Step-by-step instructions**: Numbered steps, one action per step, code blocks where applicable.
147
+ 4. **Expected result**: What the reader should see/have after completing the steps.
148
+ 5. **Troubleshooting**: Common errors and their solutions. Minimum 2 items.
149
+
150
+ Use imperative mood: "Run the command" not "You should run the command".
151
+
152
+ ### 3.4 Error Messages (dictionary kind)
153
+
154
+ Structure each error message with three parts:
155
+
156
+ 1. **What happened**: State the error clearly. "Your session has expired."
157
+ 2. **Why**: Brief explanation. "Sessions expire after 30 minutes of inactivity."
158
+ 3. **How to fix**: Actionable next step. "Sign in again to continue."
159
+
160
+ Rules:
161
+ - No blame language: "Invalid input" not "You entered invalid input".
162
+ - No technical jargon in user-facing errors.
163
+ - No naked error codes: always pair codes with human-readable text.
164
+
165
+ ### 3.5 Form Labels (dictionary kind)
166
+
167
+ - Use noun or noun phrase: "Email address", "Password", "Company name".
168
+ - Sentence case consistently: "Email address" not "Email Address".
169
+ - No colons at the end of labels.
170
+ - Helper text: one sentence explaining what to enter or format requirements.
171
+ - Consistent phrasing across all forms in the project.
172
+
173
+ ### 3.6 Navigation Items (dictionary kind)
174
+
175
+ - 1-2 words maximum.
176
+ - Use verbs for actions: "Sign in", "Download", "Contact".
177
+ - Use nouns for destinations: "Dashboard", "Settings", "Pricing".
178
+ - No abbreviations unless universally understood.
179
+ - Consistent capitalization: match the project convention.
180
+
181
+ ### 3.7 Notifications (dictionary kind)
182
+
183
+ - Start with what happened: "Your file has been uploaded."
184
+ - Include timestamp context when relevant: "2 minutes ago".
185
+ - End with next action if applicable: "View file" or "Dismiss".
186
+ - Keep under 100 characters for mobile readability.
187
+
188
+ ---
189
+
190
+ ## 4. Content Lifecycle
191
+
192
+ ### 4.1 Draft Status
193
+
194
+ - Focus on completeness over polish.
195
+ - ALL required fields must have real values — no placeholders.
196
+ - Optional fields may be empty but should be populated when possible.
197
+ - Drafts do not need final copy-editing but must be factually correct.
198
+ - Flag any fields the agent could not confidently populate.
199
+
200
+ ### 4.2 Review Status
201
+
202
+ - Vocabulary compliance: every term matches `vocabulary.json`.
203
+ - Tone consistency: matches `context.json` → `conventions.tone` throughout.
204
+ - Factual accuracy: all claims, statistics, and references are verifiable.
205
+ - Cross-locale coverage: if entry exists in source locale, all target locales must have corresponding entries.
206
+ - Field constraint compliance: all values within min/max length, pattern, and type constraints.
207
+
208
+ ### 4.3 Published Status
209
+
210
+ ALL of the following must be true:
211
+
212
+ - Every required field is populated with final content.
213
+ - Every supported locale has a complete translation.
214
+ - Zero placeholder text anywhere in the entry.
215
+ - All relation fields reference existing, published entries.
216
+ - SEO fields (title, description, slug) are populated and valid.
217
+ - Content passes tone and vocabulary checks.
218
+
219
+ ### 4.4 Archive Criteria
220
+
221
+ Move content to archived status when:
222
+
223
+ - It references deprecated features, APIs, or products.
224
+ - Dates or events referenced are more than 12 months past.
225
+ - The content has been superseded by a newer entry.
226
+ - Statistics or data points are outdated and cannot be updated.
227
+
228
+ Never delete content. Archive it. Deletion is a manual human decision.
229
+
230
+ ---
231
+
232
+ ## 5. Contentrain-Specific Rules
233
+
234
+ ### 5.1 System-Managed Fields
235
+
236
+ NEVER write to these fields — they are managed by the system:
237
+
238
+ - `id` — auto-generated unique identifier
239
+ - `createdAt` — set on creation
240
+ - `updatedAt` — set on every save
241
+ - `status` — managed through workflow transitions
242
+ - `order` — managed through UI reordering
243
+
244
+ If a write payload includes any system field, remove it before saving.
245
+
246
+ ### 5.2 Metadata Directory
247
+
248
+ - NEVER write to `.contentrain/meta/` — all metadata files are system-managed.
249
+ - NEVER modify `.contentrain/models/` directly — use MCP tools.
250
+ - Read these directories for context, but treat them as read-only.
251
+
252
+ ### 5.3 Vocabulary Usage
253
+
254
+ - Load `vocabulary.json` at the start of every content operation.
255
+ - Cross-reference every noun, verb, and technical term against the vocabulary.
256
+ - If a term is not in the vocabulary but should be, flag it for human review — do not add it.
257
+ - Vocabulary applies across ALL entries, ALL collections, ALL locales.
258
+
259
+ ### 5.4 Model Field Constraints
260
+
261
+ Before writing any field value:
262
+
263
+ 1. Read the model definition from `.contentrain/models/`.
264
+ 2. Check `required` — required fields must have non-empty values.
265
+ 3. Check `min` / `max` — string length must be within bounds.
266
+ 4. Check `pattern` — value must match regex if defined.
267
+ 5. Check `unique` — value must not duplicate any existing entry in the collection.
268
+ 6. Check `options` — if the field is an enum/select, value must be from the defined list.
269
+
270
+ Constraint violations must be fixed before saving. Never save invalid data.
271
+
272
+ ### 5.5 Collection Entry Consistency
273
+
274
+ - All entries within a collection must follow the same structural pattern.
275
+ - If existing entries use a specific content structure (e.g., all blog posts start with a hook), new entries must follow the same pattern.
276
+ - Before creating a new entry, read 2-3 existing entries to understand the established pattern.
277
+ - If no existing entries exist, follow the content type pattern defined in Section 3.
278
+
279
+ ---
280
+
281
+ ## Validation Checklist
282
+
283
+ Before committing any content, verify:
284
+
285
+ - [ ] Heading hierarchy is sequential (H1 → H2 → H3, no skips)
286
+ - [ ] Title is 50-60 characters, keyword-rich, unique
287
+ - [ ] Description is 120-160 characters, complete sentence, unique
288
+ - [ ] No placeholder text anywhere
289
+ - [ ] No duplicate content across entries
290
+ - [ ] Tone matches `context.json` configuration
291
+ - [ ] All terms match `vocabulary.json`
292
+ - [ ] All field constraints (length, pattern, required) are satisfied
293
+ - [ ] Content follows the correct content type pattern
294
+ - [ ] System fields are not included in write payload