@contentrain/rules 0.3.1 → 0.3.3

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,224 @@
1
+ # SEO Rules
2
+
3
+ These rules govern search engine optimization for all content managed through Contentrain.
4
+ Apply these rules to every content entry that produces a public-facing page.
5
+
6
+ ---
7
+
8
+ ## 1. Page Titles
9
+
10
+ ### 1.1 Length and Format
11
+
12
+ - Length: 50-60 characters including spaces. Google truncates titles beyond ~60 characters.
13
+ - Measure character count before saving. Truncated titles harm click-through rates.
14
+ - No ALL CAPS titles. Use sentence case or title case per project convention.
15
+ - No excessive punctuation: no `!!!`, no `???`, no `...` in titles.
16
+ - No emoji in titles unless explicitly configured in `context.json`.
17
+
18
+ ### 1.2 Keyword Placement
19
+
20
+ - Place the primary keyword within the first 30 characters.
21
+ - Structure: `Primary Keyword Phrase | Brand Name` or `Primary Keyword Phrase — Brand Name`.
22
+ - Acceptable separators: ` | `, ` — `, ` - `. Pick one and use it consistently across all entries.
23
+ - The keyword must read naturally — no keyword stuffing.
24
+ - GOOD: "Deploy Node.js to Production | Acme Docs"
25
+ - BAD: "Node.js Deploy Node Production Deployment | Acme"
26
+
27
+ ### 1.3 Uniqueness
28
+
29
+ - Every entry in a collection MUST have a unique title.
30
+ - Before saving, query existing entries and confirm no title collision.
31
+ - Titles across collections should also be unique when they produce public pages.
32
+
33
+ ---
34
+
35
+ ## 2. Meta Descriptions
36
+
37
+ ### 2.1 Length and Format
38
+
39
+ - Length: 120-155 characters including spaces.
40
+ - Must be a complete sentence or two short sentences.
41
+ - End with a period.
42
+ - No keyword stuffing — write for humans, not crawlers.
43
+
44
+ ### 2.2 Content Requirements
45
+
46
+ - Include a clear value proposition or call-to-action.
47
+ - GOOD: "Learn how to set up CI/CD for your Node.js project in 10 minutes. Step-by-step guide with examples."
48
+ - BAD: "CI/CD Node.js setup guide tutorial deployment continuous integration."
49
+ - Must differ from the page title — do not repeat the title as the description.
50
+ - Must be unique per entry. No two entries may share the same meta description.
51
+
52
+ ### 2.3 What to Avoid
53
+
54
+ - No quotes or special characters that break HTML meta tags: avoid `"`, `<`, `>`.
55
+ - No "Click here to learn more" — search engines ignore generic CTAs.
56
+ - No date references that will become stale (prefer "latest" over "2024").
57
+
58
+ ---
59
+
60
+ ## 3. Slugs
61
+
62
+ ### 3.1 Format
63
+
64
+ - Lowercase only. No uppercase characters.
65
+ - Words separated by hyphens (`-`). No underscores, no spaces, no dots.
66
+ - No special characters: only `a-z`, `0-9`, and `-`.
67
+ - No consecutive hyphens (`--`). No leading or trailing hyphens.
68
+
69
+ ### 3.2 Length and Content
70
+
71
+ - Optimal: 3-5 words.
72
+ - Maximum: 60 characters.
73
+ - Remove stop words (`the`, `a`, `an`, `is`, `of`, `and`, `or`, `in`, `to`) unless removing them changes meaning.
74
+ - "how-to-deploy-node" → "deploy-node" is acceptable.
75
+ - "state-of-the-art" → keep as-is because meaning changes if shortened.
76
+
77
+ ### 3.3 Stability
78
+
79
+ - NEVER change a slug on a published entry. Changing slugs breaks existing links, bookmarks, and search engine indexing.
80
+ - If a slug must change, the human must set up a redirect. The agent must not change published slugs without explicit human instruction.
81
+ - Draft entries may have their slugs changed freely before first publication.
82
+
83
+ ### 3.4 Locale Consistency
84
+
85
+ - Use the same slug value across all locales for the same entry.
86
+ - Do NOT translate slugs. Slugs are identifiers, not content.
87
+ - Example: the slug `deploy-node` remains `deploy-node` in `en`, `tr`, `de`, and all other locales.
88
+
89
+ ---
90
+
91
+ ## 4. Heading Structure
92
+
93
+ ### 4.1 H1 Rule
94
+
95
+ - Exactly one H1 per page. The H1 is the entry title or the primary heading.
96
+ - The H1 should contain the primary keyword naturally.
97
+ - Do not duplicate the H1 text elsewhere on the page.
98
+
99
+ ### 4.2 Subheading Keywords
100
+
101
+ - Include relevant keywords in H2 and H3 headings where natural.
102
+ - Do not force keywords into every heading. Clarity takes priority over keyword density.
103
+ - Use question-format headings for FAQ-style content: "How do I reset my password?"
104
+
105
+ ### 4.3 Hierarchy Reflects Content
106
+
107
+ - Heading levels must reflect the logical structure of the content.
108
+ - Do not use H3 because it renders smaller — use CSS for styling, headings for structure.
109
+ - Every heading must have content beneath it. No empty sections.
110
+ - Do not place two headings consecutively without content between them.
111
+
112
+ ---
113
+
114
+ ## 5. Images and Alt Text
115
+
116
+ ### 5.1 Alt Text Requirements
117
+
118
+ - Every `image` field that displays on a public page MUST have corresponding alt text.
119
+ - Describe the image content and its context: "Dashboard showing monthly revenue chart with 15% growth indicator."
120
+ - Maximum length: 125 characters.
121
+ - Do not start with "Image of", "Photo of", "Picture of" — describe directly.
122
+
123
+ ### 5.2 Decorative Images
124
+
125
+ - If an image is purely decorative (visual separator, background pattern), set alt text to an empty string (`""`).
126
+ - Do not omit the alt field entirely — explicitly set it to empty.
127
+
128
+ ### 5.3 Keywords in Alt Text
129
+
130
+ - Include relevant keywords naturally when they describe the image.
131
+ - Do not stuff keywords: "Node.js Node deployment Node server Node production" is forbidden.
132
+ - The alt text must accurately describe what is in the image.
133
+
134
+ ### 5.4 Image File Names
135
+
136
+ - When the agent controls the image file name, use descriptive, hyphenated names.
137
+ - GOOD: `revenue-dashboard-chart.png`
138
+ - BAD: `IMG_2847.png`, `screenshot.png`, `image1.png`
139
+
140
+ ---
141
+
142
+ ## 6. Open Graph and Social Media
143
+
144
+ ### 6.1 Open Graph Tags
145
+
146
+ When OG fields exist in the model, populate them:
147
+
148
+ | Field | Max Length | Requirement |
149
+ |---|---|---|
150
+ | `og:title` | 60 characters | Concise version of the page title |
151
+ | `og:description` | 200 characters | Slightly longer than meta description, conversational |
152
+ | `og:image` | — | 1200x630 pixels recommended, must be absolute URL |
153
+ | `og:type` | — | `article` for blog/docs, `website` for landing pages |
154
+
155
+ ### 6.2 Twitter Card
156
+
157
+ - Use `summary_large_image` for content with strong visual elements.
158
+ - Use `summary` for text-focused content.
159
+ - Twitter title and description may differ from OG — optimize for each platform.
160
+
161
+ ### 6.3 Fallback
162
+
163
+ - If OG-specific fields are absent, the system uses the standard title and description.
164
+ - Ensure the standard title and description are suitable for social sharing.
165
+
166
+ ---
167
+
168
+ ## 7. Internal Linking
169
+
170
+ ### 7.1 Relation Fields
171
+
172
+ - Use Contentrain `relation` and `relations` model fields for cross-references between entries.
173
+ - Prefer structured relations over hardcoded links in body content.
174
+ - Structured relations are maintainable — if a slug changes, relations still resolve.
175
+
176
+ ### 7.2 Bidirectional Relations
177
+
178
+ - When Entry A references Entry B, check if Entry B should reference Entry A.
179
+ - Example: if a blog post links to a product, the product's "related articles" should include that blog post.
180
+ - The agent should suggest bidirectional relations but not create them without confirmation.
181
+
182
+ ### 7.3 Manual Links in Body Content
183
+
184
+ - If the model does not have relation fields and links must be in body text, use relative paths.
185
+ - Verify that linked entries exist before saving.
186
+ - Do not link to draft or archived entries from published content.
187
+
188
+ ---
189
+
190
+ ## 8. URL and Canonical Rules
191
+
192
+ ### 8.1 Slug Patterns
193
+
194
+ - All entries in a collection must follow the same slug pattern.
195
+ - If existing entries use `verb-noun` format (e.g., `deploy-app`, `configure-server`), new entries must follow the same pattern.
196
+ - Check existing entries before generating a slug for a new entry.
197
+
198
+ ### 8.2 Multi-Locale URLs
199
+
200
+ - Same slug across all locales (see Section 3.4).
201
+ - Locale prefix is handled by the frontend routing, not by the content slug.
202
+ - Example: `/en/deploy-node` and `/tr/deploy-node` share the slug `deploy-node`.
203
+
204
+ ### 8.3 Trailing Slashes
205
+
206
+ - The agent does not control trailing slash behavior — this is a frontend routing concern.
207
+ - Ensure slug values do not include leading or trailing slashes.
208
+
209
+ ---
210
+
211
+ ## Validation Checklist
212
+
213
+ Before committing any content with SEO impact, verify:
214
+
215
+ - [ ] Title is 50-60 characters, primary keyword near start, unique
216
+ - [ ] Meta description is 120-155 characters, complete sentence, unique
217
+ - [ ] Slug is lowercase, hyphenated, 3-5 words, no special characters
218
+ - [ ] Published slugs have not been changed
219
+ - [ ] Slugs are identical across all locales for the same entry
220
+ - [ ] One H1 per page, sequential heading hierarchy
221
+ - [ ] All images have descriptive alt text (max 125 chars) or empty string for decorative
222
+ - [ ] OG fields populated if model supports them
223
+ - [ ] Relation fields used for internal cross-references
224
+ - [ ] No keyword stuffing in titles, descriptions, headings, or alt text
@@ -0,0 +1,317 @@
1
+ # Contentrain Workflow Rules
2
+
3
+ > These rules govern how content changes flow through the Git-based workflow, including branching, validation, review, and status management.
4
+
5
+ ---
6
+
7
+ ## 1. Two Workflow Modes
8
+
9
+ Contentrain supports two workflow modes, configured in `.contentrain/config.json` under the `workflow` field.
10
+
11
+ ### 1.1 auto-merge
12
+
13
+ ```json
14
+ { "workflow": "auto-merge" }
15
+ ```
16
+
17
+ - Feature branch is created from the `contentrain` branch, changes are committed, feature branch is **merged into `contentrain`**, then baseBranch is advanced via **update-ref** (fast-forward), and `.contentrain/` files are **selectively synced** to the developer's working tree.
18
+ - No review step -- changes go live immediately.
19
+ - Best for: solo developers, rapid iteration, prototyping, vibe coding.
20
+ - Status flow: `draft` --> `published` (skips `in_review`).
21
+
22
+ ### 1.2 review
23
+
24
+ ```json
25
+ { "workflow": "review" }
26
+ ```
27
+
28
+ - Branch is created, changes are committed, branch is **pushed to remote**.
29
+ - Studio or team reviews the changes before merging.
30
+ - Best for: teams, content governance, production environments.
31
+ - Status flow: `draft` --> `in_review` --> `published` | `rejected`.
32
+
33
+ ### 1.3 Mode Selection Rules
34
+
35
+ - Default is `auto-merge` -- minimal friction for getting started.
36
+ - Switch to `review` as the project or team grows and governance becomes important.
37
+ - **Normalize operations ALWAYS use `review` mode** regardless of the config setting. Normalize changes are never auto-merged.
38
+
39
+ ---
40
+
41
+ ## 2. Branch Naming Convention
42
+
43
+ All Contentrain branches follow a strict naming pattern:
44
+
45
+ ```
46
+ contentrain/{operation}/{model}/{locale}/{timestamp}
47
+ ```
48
+
49
+ ### Examples
50
+
51
+ | Scenario | Branch Name |
52
+ |----------|-------------|
53
+ | Content update | `contentrain/content/blog-post/en/1710300000` |
54
+ | Model creation | `contentrain/model/team-member/1710300000` |
55
+ | Normalize extraction | `contentrain/normalize/extract/blog/1710300000` |
56
+ | Normalize reuse | `contentrain/normalize/reuse/marketing-hero/en/1710300000` |
57
+ | Scaffold | `contentrain/new/scaffold-landing/en/1710300000` |
58
+
59
+ ### Rules
60
+
61
+ - Branches are created automatically by MCP tools. Do NOT create them manually.
62
+ - The `{timestamp}` component ensures uniqueness.
63
+ - `{locale}` is included when the operation is locale-specific.
64
+ - `{model}` is included when the operation targets a specific model.
65
+
66
+ ---
67
+
68
+ ## 3. Git Workflow
69
+
70
+ ### 3.1 Dedicated `contentrain` Branch
71
+
72
+ The `contentrain` branch is the **single source of truth** for content state:
73
+
74
+ - Created automatically at `contentrain_init`.
75
+ - All content writes happen on feature branches forked from `contentrain`.
76
+ - The `contentrain` branch is **protected from deletion**.
77
+ - context.json is committed together with content changes, not as a separate commit.
78
+
79
+ ### 3.2 Worktree-Based Transactions
80
+
81
+ Every write operation follows this flow:
82
+
83
+ 1. MCP creates a **temporary Git worktree** on a new feature branch forked from `contentrain`.
84
+ 2. Changes are made in the worktree (content files, model files, context.json).
85
+ 3. Changes are committed to the feature branch.
86
+ 4. **auto-merge mode:** Feature branch is merged into `contentrain`, then baseBranch is advanced via **update-ref** (fast-forward), then `.contentrain/` files are **selectively synced** to the developer's working tree. Dirty files are skipped with a warning. Worktree is cleaned up.
87
+ 5. **review mode:** Feature branch is pushed to remote for team review. Worktree is cleaned up. Studio notifies reviewers.
88
+
89
+ Developer's working tree is **never mutated** during MCP git operations. There is no stash, no checkout, and no merge on the developer's tree.
90
+
91
+ ### 3.3 Developer Manual Editing
92
+
93
+ If the developer manually edits `.contentrain/` files in their working tree, MCP selective sync skips those dirty files and issues a warning. The developer must commit or discard their local changes before MCP can sync those files.
94
+
95
+ ### 3.4 Critical Rules
96
+
97
+ - **NEVER commit directly to main or the `contentrain` branch.** All changes go through feature branches.
98
+ - **NEVER create branches manually.** MCP tools handle all Git operations.
99
+ - **NEVER force-push or rebase** Contentrain branches.
100
+ - **NEVER delete the `contentrain` branch.** It is the content state SSOT.
101
+ - Worktrees are temporary. They are created for the operation and cleaned up afterward.
102
+ - Each branch contains a cohesive set of changes (e.g., all entries for one model update).
103
+
104
+ ### 3.5 Branch Lifecycle
105
+
106
+ ```
107
+ Feature branch created (worktree on contentrain)
108
+ --> Changes committed
109
+ --> auto-merge: feature merged into contentrain
110
+ --> update-ref advances baseBranch
111
+ --> selective sync .contentrain/ to developer's tree
112
+ --> review: feature pushed to remote, awaiting review
113
+ --> Worktree cleaned up
114
+ ```
115
+
116
+ The `contentrain` branch is permanent and protected. Feature branches are retained for `branchRetention` days (default: 30) for audit trail, then pruned.
117
+
118
+ ### 3.6 Branch Health
119
+
120
+ MCP enforces branch health limits to prevent branch accumulation:
121
+
122
+ - **50+ active branches**: Warning. Operations continue but the user is alerted.
123
+ - **80+ active branches**: Blocked. No new write operations until branches are merged or deleted.
124
+ - `contentrain_status` reports branch health automatically (total, merged, unmerged counts).
125
+ - Merged branches are cleaned up lazily during status checks and submit operations.
126
+
127
+ ---
128
+
129
+ ## 4. Conflict Resolution
130
+
131
+ ### 4.1 How Conflicts Are Minimized
132
+
133
+ Contentrain's storage format is designed to minimize Git merge conflicts:
134
+
135
+ - **Object-map storage** for collections: each entry is a separate key-value pair. Two branches adding different entries rarely conflict.
136
+ - **Canonical serialization**: sorted keys and deterministic formatting prevent artificial diffs.
137
+ - **Review mode for normalize**: separate branches for extraction and reuse reduce concurrent editing conflicts.
138
+
139
+ ### 4.2 When Conflicts Occur
140
+
141
+ | Scenario | Likelihood | Resolution |
142
+ |----------|-----------|------------|
143
+ | Different fields on the same entry | Low | Auto-merge succeeds (JSON field-level merge) |
144
+ | Same field changed by two branches | Medium | Studio conflict resolution UI |
145
+ | Two entries added with adjacent IDs | Very low | Auto-merge usually succeeds |
146
+ | Concurrent normalize operations | Avoided | Always review mode, sequential per model |
147
+
148
+ ### 4.3 Conflict Resolution Rules
149
+
150
+ - Field-level merge for JSON: if the same entry has different fields changed in two branches, Git auto-merges.
151
+ - Same field changed by multiple branches creates a conflict requiring Studio resolution.
152
+ - When a conflict occurs, the agent should NOT attempt to resolve it. Inform the user and direct them to Studio.
153
+ - Collection object-map format with sorted keys means ~0.3% chance of conflict for two new entries in a 350-entry collection.
154
+
155
+ ---
156
+
157
+ ## 5. Workflow States
158
+
159
+ Content entries move through these states:
160
+
161
+ ```
162
+ draft --> in_review --> published
163
+ |
164
+ v
165
+ rejected (with feedback)
166
+
167
+ published --> archived
168
+ ```
169
+
170
+ ### 5.1 State Definitions
171
+
172
+ | State | Git State | Trigger |
173
+ |-------|-----------|---------|
174
+ | `draft` | Branch exists, not yet reviewed/merged | Content created or updated |
175
+ | `in_review` | PR/branch open, labeled `contentrain-content` | `contentrain_submit` in review mode |
176
+ | `published` | Content is on `contentrain` branch and synced to baseBranch | Auto-merge, or PR merged after review |
177
+ | `rejected` | PR closed without merge | Studio reviewer rejects changes |
178
+ | `archived` | Metadata-only state | Manual action -- content hidden but retained |
179
+
180
+ ### 5.2 State Rules
181
+
182
+ - **State is tracked in `.contentrain/meta/`, NOT in content files.** Agents never read or write state directly.
183
+ - **auto-merge mode:** `draft` --> `published` (no `in_review` step).
184
+ - **review mode:** `draft` --> `in_review` --> `published` or `rejected`.
185
+ - **Git is the source of truth.** States are derived from Git state (branch existence, merge status, PR status).
186
+ - Rejected content includes reviewer feedback. The agent can address feedback and resubmit.
187
+
188
+ ---
189
+
190
+ ## 6. Validation Rules
191
+
192
+ ### 6.1 When to Validate
193
+
194
+ - ALWAYS call `contentrain_validate` before `contentrain_submit`.
195
+ - `contentrain_submit` will fail if validation errors exist.
196
+ - Run validation after completing all changes in a batch, not after every individual save.
197
+
198
+ ### 6.2 What Validation Checks
199
+
200
+ | Check | Severity | Description |
201
+ |-------|----------|-------------|
202
+ | Schema compliance | Error | Field values match their type definitions |
203
+ | Required fields | Error | All `required: true` fields have values |
204
+ | Unique constraints | Error | `unique: true` fields have no duplicates within the model |
205
+ | Locale completeness | Error/Warning | All supported locales have corresponding files and entries |
206
+ | Referential integrity | Error | Relation targets (IDs/slugs) exist in the target model |
207
+ | Canonical format | Warning | Files follow canonical serialization rules |
208
+ | Vocabulary usage | Warning | Content uses vocabulary terms when available |
209
+
210
+ ### 6.3 Handling Validation Results
211
+
212
+ - **Errors:** MUST be fixed before submitting. Fix the content and re-validate.
213
+ - **Warnings:** Acceptable but should be addressed when possible. Acknowledge them before submitting.
214
+ - If validation returns zero errors, proceed with `contentrain_submit`.
215
+
216
+ ---
217
+
218
+ ## 7. Submit Behavior
219
+
220
+ ### 7.1 auto-merge Mode
221
+
222
+ ```
223
+ contentrain_submit
224
+ --> Merge feature branch into contentrain
225
+ --> Advance baseBranch via update-ref (fast-forward)
226
+ --> Selectively sync .contentrain/ files to developer's working tree
227
+ --> Clean up worktree
228
+ --> Status: published
229
+ ```
230
+
231
+ ### 7.2 review Mode
232
+
233
+ ```
234
+ contentrain_submit
235
+ --> Push feature branch to remote
236
+ --> Clean up worktree
237
+ --> Status: in_review
238
+ --> Studio notifies reviewers
239
+ ```
240
+
241
+ ### 7.3 Submit Rules
242
+
243
+ - Submit operates on the current pending branch. There must be pending changes.
244
+ - If no changes are pending, submit is a no-op.
245
+ - After submit, the agent can continue with other operations (new branch will be created for new changes).
246
+ - Normalize operations ALWAYS submit in review mode, regardless of project workflow setting.
247
+
248
+ ### 7.4 Branch Merge Mechanisms
249
+
250
+ Review-mode branches can be merged three ways:
251
+
252
+ **1. CLI Serve UI (Browser — recommended for normalize)**
253
+
254
+ ```bash
255
+ contentrain serve
256
+ ```
257
+
258
+ Navigate to http://localhost:3333/branches → select branch → click Merge.
259
+
260
+ **2. MCP Tool (Programmatic — for agent-driven workflows)**
261
+
262
+ ```
263
+ contentrain_merge(branch: "cr/normalize/extract/...", confirm: true)
264
+ ```
265
+
266
+ Local git merge: feature → contentrain → update-ref → selective sync.
267
+ No external platform required. Agent can continue immediately.
268
+
269
+ **3. Git Platform (GitHub/GitLab — for team governance)**
270
+
271
+ ```
272
+ contentrain_submit # pushes to remote
273
+ ```
274
+
275
+ Then create PR on platform → review → merge.
276
+
277
+ **Agent Decision Guide:**
278
+
279
+ | Workflow | Recommended Merge Method |
280
+ |----------|--------------------------|
281
+ | Normalize (extract/reuse) | CLI serve UI (visual review of content) |
282
+ | Content CRUD | `contentrain_merge` (programmatic, fast) |
283
+ | Team with code review | Git platform PR |
284
+
285
+ ---
286
+
287
+ ## 8. Metadata Structure
288
+
289
+ Metadata files track governance information. They are system-managed -- agents NEVER write to them.
290
+
291
+ ### File Paths
292
+
293
+ | Kind | Path |
294
+ |------|------|
295
+ | Singleton / Dictionary | `.contentrain/meta/{modelId}/{locale}.json` |
296
+ | Collection | `.contentrain/meta/{modelId}/{locale}.json` (object-map: `{ entryId: meta }`) |
297
+ | Document | `.contentrain/meta/{modelId}/{slug}/{locale}.json` |
298
+
299
+ ### Metadata Fields
300
+
301
+ ```json
302
+ {
303
+ "status": "published",
304
+ "source": "agent",
305
+ "updated_by": "claude",
306
+ "approved_by": "ahmet@contentrain.io",
307
+ "version": "1"
308
+ }
309
+ ```
310
+
311
+ | Field | Values | Description |
312
+ |-------|--------|-------------|
313
+ | `status` | `draft`, `in_review`, `published`, `rejected`, `archived` | Current workflow state |
314
+ | `source` | `agent`, `human`, `import` | How the content was created |
315
+ | `updated_by` | string | Agent name or user email |
316
+ | `approved_by` | string or null | Who approved (review mode only) |
317
+ | `version` | string | Content version identifier |