@contentrain/rules 0.3.3 → 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.
package/README.md CHANGED
@@ -10,15 +10,16 @@ Shared AI-agent rules for Contentrain.
10
10
  Start here:
11
11
 
12
12
  - [2-minute product demo](https://ai.contentrain.io/demo)
13
- - [Rules & skills docs](https://ai.contentrain.io/packages/rules)
13
+ - [Rules & skills docs](https://ai.contentrain.io/packages/rules)
14
14
 
15
- This package is the policy layer of the Contentrain ecosystem. It defines how agents should behave when they work with:
15
+ This package is the **policy layer** of the Contentrain ecosystem. It defines how agents should behave when they work with:
16
16
 
17
- - Contentrain MCP tools
17
+ - Contentrain MCP tools (17 operations)
18
18
  - schema and model design
19
- - content quality
20
- - normalize workflows
19
+ - content quality (SEO, accessibility, media, i18n)
20
+ - normalize workflows (extraction + reuse)
21
21
  - git-backed review flows
22
+ - security guardrails
22
23
 
23
24
  If `@contentrain/mcp` is the deterministic execution layer, `@contentrain/rules` is the behavioral contract.
24
25
 
@@ -32,71 +33,100 @@ pnpm add @contentrain/rules
32
33
 
33
34
  ### Essential guardrails
34
35
 
35
- Published under `essential/*`:
36
+ Published under `essential/`:
36
37
 
37
- - `contentrain-essentials.md` — compact, always-loaded rules (~86 lines) covering architecture, model kinds, MCP tools, mandatory protocols, and security basics
38
+ - `contentrain-essentials.md` — compact, always-loaded rules covering architecture, model kinds, MCP tools, mandatory protocols, git workflow, and security basics.
39
+
40
+ ### Shared quality rules
41
+
42
+ Published under `shared/` — detailed standards per domain:
43
+
44
+ - `content-quality.md` — structure, required fields, content completeness
45
+ - `seo-rules.md` — meta optimization, keywords, canonical URLs
46
+ - `accessibility-rules.md` — alt text, ARIA labels, color contrast
47
+ - `media-rules.md` — image optimization, responsive sizing, asset naming
48
+ - `schema-rules.md` — model design, field types, relations, inheritance
49
+ - `i18n-quality.md` — translation completeness, locale parity
50
+ - `security-rules.md` — sensitive data patterns, secret detection, XSS prevention
51
+ - `mcp-usage.md` — tool invocation patterns, git workflows, trust levels
52
+ - `normalize-rules.md` — extraction and reuse constraints, scope safety
53
+ - `workflow-rules.md` — review mode, approval flows, branch lifecycle
54
+ - `content-conventions.md` — naming, slug generation, status conventions
38
55
 
39
56
  ### Prompt layers
40
57
 
41
- Published under `prompts/*`:
58
+ Published under `prompts/` — mode-specific context the agent loads per task:
42
59
 
43
- - `common.md`
44
- - `generate-mode.md`
45
- - `normalize-mode.md`
46
- - `review-mode.md`
60
+ - `common.md` — shared preamble for all agent modes
61
+ - `generate-mode.md` — content creation constraints
62
+ - `normalize-mode.md` — string extraction and patching workflows
63
+ - `review-mode.md` — content validation and change review
47
64
 
48
65
  ### Context bridge
49
66
 
50
- Published under `context/*`:
67
+ Published under `context/`:
51
68
 
52
- - `context-bridge.md`
69
+ - `context-bridge.md` — how to integrate rules into agent context systems
70
+ - `templates/` — framework-specific context JSON for `nuxt`, `next`, `astro`, `sveltekit`
53
71
 
54
72
  ## Public Exports
55
73
 
56
- The package root exports constants that can be used by tooling:
74
+ The package root exports constants for tooling:
57
75
 
58
76
  - `FIELD_TYPES` — 27 flat field types
59
- - `MODEL_KINDS` — singleton, collection, document, dictionary
60
- - `MCP_TOOLS` — 15 MCP tool names
77
+ - `MODEL_KINDS` — `singleton`, `collection`, `document`, `dictionary`
78
+ - `MCP_TOOLS` — 17 MCP tool names (includes `contentrain_merge` and `contentrain_doctor`)
61
79
  - `ESSENTIAL_RULES_FILE` — path to essential guardrails markdown
62
80
  - `STACKS` — supported framework stacks
63
81
 
64
- ## Example
82
+ ## Quick Example
65
83
 
66
84
  ```ts
67
85
  import { MCP_TOOLS, ESSENTIAL_RULES_FILE, FIELD_TYPES } from '@contentrain/rules'
68
86
 
69
- console.log(MCP_TOOLS.includes('contentrain_validate'))
70
- console.log(ESSENTIAL_RULES_FILE) // 'essential/contentrain-essentials.md'
71
- console.log(FIELD_TYPES.length) // 27
87
+ console.log(MCP_TOOLS.length) // 17
88
+ console.log(MCP_TOOLS.includes('contentrain_merge')) // true
89
+ console.log(MCP_TOOLS.includes('contentrain_doctor')) // true
90
+ console.log(ESSENTIAL_RULES_FILE) // 'essential/contentrain-essentials.md'
91
+ console.log(FIELD_TYPES.length) // 27
72
92
  ```
73
93
 
74
94
  ## Design Role
75
95
 
76
96
  `@contentrain/rules` exists to keep agent behavior aligned across tools and environments.
77
97
 
78
- It should answer questions like:
98
+ Typical questions it answers:
99
+
100
+ - What is acceptable content quality? (shared quality rules)
101
+ - How should an agent use MCP tools safely? (mcp-usage + tool reference)
102
+ - What is the normalize contract? (normalize-rules)
103
+ - What workflow and review constraints exist? (workflow-rules)
104
+
105
+ Detailed procedures and step-by-step guides live in `@contentrain/skills` (Agent Skills standard format).
106
+
107
+ ## Parity with `@contentrain/mcp`
108
+
109
+ `@contentrain/rules` is kept in lockstep with the MCP tool registry via cross-package parity tests. When a new MCP tool is registered in `@contentrain/mcp`:
79
110
 
80
- - What is acceptable content quality?
81
- - How should an agent use MCP tools?
82
- - What is the normalize contract?
83
- - What workflow and review constraints exist?
111
+ - `MCP_TOOLS` must include it (otherwise `tests/mcp-parity.test.ts` fails)
112
+ - the essentials document must mention it
113
+ - the skills reference must have a `### <tool>` section
84
114
 
85
- Detailed reference material and step-by-step procedures live in `@contentrain/skills` (Agent Skills standard format).
115
+ When MCP's branch-naming convention changes (e.g. `contentrain/*` → `cr/*`), the rules prose must follow — the parity test scans the rules for the legacy prefix and fails if it reappears.
86
116
 
87
117
  ## Relationship To Other Packages
88
118
 
89
119
  - `@contentrain/mcp` enforces file, validation, and git behavior
90
120
  - `@contentrain/skills` provides Agent Skills with progressive disclosure (SKILL.md + references/)
91
- - `contentrain` exposes CLI and serve UX
121
+ - `contentrain` (CLI) installs rules + skills into the IDE during `contentrain init`
92
122
  - `@contentrain/query` is the generated runtime consumption layer
93
123
 
94
124
  Rule of thumb:
95
125
 
96
- - `rules` = essential guardrails (always loaded, ~86 lines)
97
- - `skills` = detailed procedures and reference docs (on-demand)
126
+ - `rules` = policy layer (quality standards, constraints, essentials)
127
+ - `skills` = procedural layer (workflows, detailed reference docs)
98
128
 
99
- See [`AGENTS.md`](../../AGENTS.md) at the repo root for agent-level project guidance.
129
+ See [`AGENTS.md`](../../AGENTS.md) at the repo root for project-level agent guidance.
100
130
 
101
131
  ## Build
102
132
 
package/dist/index.cjs CHANGED
@@ -55,7 +55,9 @@ const MCP_TOOLS = [
55
55
  "contentrain_apply",
56
56
  "contentrain_validate",
57
57
  "contentrain_submit",
58
- "contentrain_bulk"
58
+ "contentrain_merge",
59
+ "contentrain_bulk",
60
+ "contentrain_doctor"
59
61
  ];
60
62
  const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
61
63
  const STACKS = [
package/dist/index.d.cts CHANGED
@@ -8,7 +8,7 @@ declare const FIELD_TYPES: readonly ["string", "text", "email", "url", "slug", "
8
8
  type FieldType = (typeof FIELD_TYPES)[number];
9
9
  declare const MODEL_KINDS: readonly ["singleton", "collection", "document", "dictionary"];
10
10
  type ModelKind = (typeof MODEL_KINDS)[number];
11
- declare const MCP_TOOLS: readonly ["contentrain_status", "contentrain_describe", "contentrain_describe_format", "contentrain_init", "contentrain_scaffold", "contentrain_model_save", "contentrain_model_delete", "contentrain_content_save", "contentrain_content_delete", "contentrain_content_list", "contentrain_scan", "contentrain_apply", "contentrain_validate", "contentrain_submit", "contentrain_bulk"];
11
+ declare const MCP_TOOLS: readonly ["contentrain_status", "contentrain_describe", "contentrain_describe_format", "contentrain_init", "contentrain_scaffold", "contentrain_model_save", "contentrain_model_delete", "contentrain_content_save", "contentrain_content_delete", "contentrain_content_list", "contentrain_scan", "contentrain_apply", "contentrain_validate", "contentrain_submit", "contentrain_merge", "contentrain_bulk", "contentrain_doctor"];
12
12
  type McpTool = (typeof MCP_TOOLS)[number];
13
13
  declare const ESSENTIAL_RULES_FILE: "essential/contentrain-essentials.md";
14
14
  declare const STACKS: readonly ["nuxt", "next", "astro", "sveltekit", "react", "node"];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;AAQA;;;;cAAa,WAAA;AAAA,KAUD,SAAA,WAAoB,WAAA;AAAA,cAInB,WAAA;AAAA,KACD,SAAA,WAAoB,WAAA;AAAA,cAInB,SAAA;AAAA,KAUD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/index.ts"],"mappings":";;AAQA;;;;cAAa,WAAA;AAAA,KAUD,SAAA,WAAoB,WAAA;AAAA,cAInB,WAAA;AAAA,KACD,SAAA,WAAoB,WAAA;AAAA,cAInB,SAAA;AAAA,KAYD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
package/dist/index.d.mts CHANGED
@@ -8,7 +8,7 @@ declare const FIELD_TYPES: readonly ["string", "text", "email", "url", "slug", "
8
8
  type FieldType = (typeof FIELD_TYPES)[number];
9
9
  declare const MODEL_KINDS: readonly ["singleton", "collection", "document", "dictionary"];
10
10
  type ModelKind = (typeof MODEL_KINDS)[number];
11
- declare const MCP_TOOLS: readonly ["contentrain_status", "contentrain_describe", "contentrain_describe_format", "contentrain_init", "contentrain_scaffold", "contentrain_model_save", "contentrain_model_delete", "contentrain_content_save", "contentrain_content_delete", "contentrain_content_list", "contentrain_scan", "contentrain_apply", "contentrain_validate", "contentrain_submit", "contentrain_bulk"];
11
+ declare const MCP_TOOLS: readonly ["contentrain_status", "contentrain_describe", "contentrain_describe_format", "contentrain_init", "contentrain_scaffold", "contentrain_model_save", "contentrain_model_delete", "contentrain_content_save", "contentrain_content_delete", "contentrain_content_list", "contentrain_scan", "contentrain_apply", "contentrain_validate", "contentrain_submit", "contentrain_merge", "contentrain_bulk", "contentrain_doctor"];
12
12
  type McpTool = (typeof MCP_TOOLS)[number];
13
13
  declare const ESSENTIAL_RULES_FILE: "essential/contentrain-essentials.md";
14
14
  declare const STACKS: readonly ["nuxt", "next", "astro", "sveltekit", "react", "node"];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;AAQA;;;;cAAa,WAAA;AAAA,KAUD,SAAA,WAAoB,WAAA;AAAA,cAInB,WAAA;AAAA,KACD,SAAA,WAAoB,WAAA;AAAA,cAInB,SAAA;AAAA,KAUD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/index.ts"],"mappings":";;AAQA;;;;cAAa,WAAA;AAAA,KAUD,SAAA,WAAoB,WAAA;AAAA,cAInB,WAAA;AAAA,KACD,SAAA,WAAoB,WAAA;AAAA,cAInB,SAAA;AAAA,KAYD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
package/dist/index.mjs CHANGED
@@ -54,7 +54,9 @@ const MCP_TOOLS = [
54
54
  "contentrain_apply",
55
55
  "contentrain_validate",
56
56
  "contentrain_submit",
57
- "contentrain_bulk"
57
+ "contentrain_merge",
58
+ "contentrain_bulk",
59
+ "contentrain_doctor"
58
60
  ];
59
61
  const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
60
62
  const STACKS = [
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @contentrain/rules — AI agent rules for Contentrain\n *\n * Quality standards, architecture conventions, and IDE integration.\n */\n\n// ─── Field Types (27 flat types) ───\n\nexport const FIELD_TYPES = [\n 'string', 'text', 'email', 'url', 'slug', 'color', 'phone', 'code', 'icon',\n 'markdown', 'richtext',\n 'number', 'integer', 'decimal', 'percent', 'rating',\n 'boolean', 'date', 'datetime',\n 'image', 'video', 'file',\n 'relation', 'relations',\n 'select', 'array', 'object',\n] as const\n\nexport type FieldType = (typeof FIELD_TYPES)[number]\n\n// ─── Model Kinds ───\n\nexport const MODEL_KINDS = ['singleton', 'collection', 'document', 'dictionary'] as const\nexport type ModelKind = (typeof MODEL_KINDS)[number]\n\n// ─── MCP Tools (15 tools) ───\n\nexport const MCP_TOOLS = [\n 'contentrain_status', 'contentrain_describe', 'contentrain_describe_format',\n 'contentrain_init', 'contentrain_scaffold',\n 'contentrain_model_save', 'contentrain_model_delete',\n 'contentrain_content_save', 'contentrain_content_delete', 'contentrain_content_list',\n 'contentrain_scan', 'contentrain_apply',\n 'contentrain_validate', 'contentrain_submit',\n 'contentrain_bulk',\n] as const\n\nexport type McpTool = (typeof MCP_TOOLS)[number]\n\n// ─── Essential Rules ───\n\nexport const ESSENTIAL_RULES_FILE = 'essential/contentrain-essentials.md' as const\n\n// ─── Stacks ───\n\nexport const STACKS = ['nuxt', 'next', 'astro', 'sveltekit', 'react', 'node'] as const\nexport type Stack = (typeof STACKS)[number]\n"],"mappings":";;;;;;AAQA,MAAa,cAAc;CACzB;CAAU;CAAQ;CAAS;CAAO;CAAQ;CAAS;CAAS;CAAQ;CACpE;CAAY;CACZ;CAAU;CAAW;CAAW;CAAW;CAC3C;CAAW;CAAQ;CACnB;CAAS;CAAS;CAClB;CAAY;CACZ;CAAU;CAAS;CACpB;AAMD,MAAa,cAAc;CAAC;CAAa;CAAc;CAAY;CAAa;AAKhF,MAAa,YAAY;CACvB;CAAsB;CAAwB;CAC9C;CAAoB;CACpB;CAA0B;CAC1B;CAA4B;CAA8B;CAC1D;CAAoB;CACpB;CAAwB;CACxB;CACD;AAMD,MAAa,uBAAuB;AAIpC,MAAa,SAAS;CAAC;CAAQ;CAAQ;CAAS;CAAa;CAAS;CAAO"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * @contentrain/rules — AI agent rules for Contentrain\n *\n * Quality standards, architecture conventions, and IDE integration.\n */\n\n// ─── Field Types (27 flat types) ───\n\nexport const FIELD_TYPES = [\n 'string', 'text', 'email', 'url', 'slug', 'color', 'phone', 'code', 'icon',\n 'markdown', 'richtext',\n 'number', 'integer', 'decimal', 'percent', 'rating',\n 'boolean', 'date', 'datetime',\n 'image', 'video', 'file',\n 'relation', 'relations',\n 'select', 'array', 'object',\n] as const\n\nexport type FieldType = (typeof FIELD_TYPES)[number]\n\n// ─── Model Kinds ───\n\nexport const MODEL_KINDS = ['singleton', 'collection', 'document', 'dictionary'] as const\nexport type ModelKind = (typeof MODEL_KINDS)[number]\n\n// ─── MCP Tools (17 tools) ───\n\nexport const MCP_TOOLS = [\n 'contentrain_status', 'contentrain_describe', 'contentrain_describe_format',\n 'contentrain_init', 'contentrain_scaffold',\n 'contentrain_model_save', 'contentrain_model_delete',\n 'contentrain_content_save', 'contentrain_content_delete', 'contentrain_content_list',\n 'contentrain_scan', 'contentrain_apply',\n 'contentrain_validate', 'contentrain_submit',\n 'contentrain_merge',\n 'contentrain_bulk',\n 'contentrain_doctor',\n] as const\n\nexport type McpTool = (typeof MCP_TOOLS)[number]\n\n// ─── Essential Rules ───\n\nexport const ESSENTIAL_RULES_FILE = 'essential/contentrain-essentials.md' as const\n\n// ─── Stacks ───\n\nexport const STACKS = ['nuxt', 'next', 'astro', 'sveltekit', 'react', 'node'] as const\nexport type Stack = (typeof STACKS)[number]\n"],"mappings":";;;;;;AAQA,MAAa,cAAc;CACzB;CAAU;CAAQ;CAAS;CAAO;CAAQ;CAAS;CAAS;CAAQ;CACpE;CAAY;CACZ;CAAU;CAAW;CAAW;CAAW;CAC3C;CAAW;CAAQ;CACnB;CAAS;CAAS;CAClB;CAAY;CACZ;CAAU;CAAS;CACpB;AAMD,MAAa,cAAc;CAAC;CAAa;CAAc;CAAY;CAAa;AAKhF,MAAa,YAAY;CACvB;CAAsB;CAAwB;CAC9C;CAAoB;CACpB;CAA0B;CAC1B;CAA4B;CAA8B;CAC1D;CAAoB;CACpB;CAAwB;CACxB;CACA;CACA;CACD;AAMD,MAAa,uBAAuB;AAIpC,MAAa,SAAS;CAAC;CAAQ;CAAQ;CAAS;CAAa;CAAS;CAAO"}
@@ -54,6 +54,7 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
54
54
  | `contentrain_submit` | Push branches to remote |
55
55
  | `contentrain_merge` | Merge a review-mode branch into contentrain locally |
56
56
  | `contentrain_bulk` | Batch operations (copy_locale/update_status/delete_entries) |
57
+ | `contentrain_doctor` | Project health report (env + structure + orphan content + branch pressure + SDK freshness) |
57
58
 
58
59
  ## Mandatory Protocols
59
60
 
@@ -68,7 +69,7 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
68
69
 
69
70
  - A dedicated `contentrain` branch is the single source of truth for content state, created at init
70
71
  - Every write operation creates a temporary worktree on the `contentrain` branch automatically
71
- - Feature branches (`contentrain/{operation}/{model}/{locale}/{timestamp}`) are created from `contentrain` for each operation
72
+ - Feature branches (`cr/{operation}/{model}/{locale}/{timestamp}`) are created from `contentrain` for each operation
72
73
  - **auto-merge** mode: feature branch merges into `contentrain`, then `contentrain` advances baseBranch via update-ref (fast-forward), then `.contentrain/` files are selectively synced to the developer's working tree
73
74
  - **review** mode: feature branch pushed to remote for team review
74
75
  - Developer's working tree is never mutated during MCP git operations (no stash, no checkout, no merge on the developer's tree)
@@ -76,7 +77,7 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
76
77
  - The `contentrain` branch is protected from deletion
77
78
  - context.json is committed together with content changes, not as a separate commit
78
79
  - Never create branches manually, never commit directly to main or the `contentrain` branch
79
- - 50+ active branches = warning, 80+ = blocked
80
+ - 50+ active `cr/*` branches = warning, 80+ = blocked
80
81
 
81
82
  ## CLI Serve — Review & Approval
82
83
 
@@ -111,6 +112,13 @@ This regenerates `.contentrain/client/` — required for `#contentrain` imports
111
112
  - Collection entry IDs and dictionary keys must match across all locales
112
113
  - IDs and slugs are locale-agnostic — same reference works everywhere
113
114
 
115
+ ## Content Governance
116
+
117
+ - **No duplicate values** — before creating a dictionary key, check if the value already exists under another key (MCP warns automatically via advisories)
118
+ - **Vocabulary first** — check `.contentrain/vocabulary.json` for canonical terms before creating content. Use approved terms exactly, do not invent synonyms
119
+ - **Run validation** — after bulk content operations, call `contentrain_validate` to catch duplicate values, missing translations, and schema issues
120
+ - **Periodic health check** — run `contentrain doctor --usage` to detect unused keys, duplicate values, and locale coverage gaps
121
+
114
122
  ## Security
115
123
 
116
124
  - No `<script>`, `javascript:`, or event handlers in richtext/markdown
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/rules",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "license": "MIT",
5
5
  "description": "AI agent rules for Contentrain — quality standards, architecture conventions, IDE integration",
6
6
  "type": "module",
@@ -54,7 +54,8 @@
54
54
  "@types/node": "^22.0.0",
55
55
  "tsdown": "^0.21.0",
56
56
  "typescript": "^5.7.0",
57
- "vitest": "^3.0.0"
57
+ "vitest": "^3.0.0",
58
+ "@contentrain/mcp": "1.3.0"
58
59
  },
59
60
  "scripts": {
60
61
  "build": "tsdown src/index.ts --format esm,cjs --dts",
@@ -12,7 +12,7 @@ This mode converts a codebase with hardcoded strings into a Contentrain-managed
12
12
  |--------|---------------------|----------------|
13
13
  | Purpose | Pull content from source code into `.contentrain/` | Patch source files to reference extracted content |
14
14
  | Source files modified | No | Yes |
15
- | Branch pattern | `contentrain/normalize/extract/{domain}/{timestamp}` | `contentrain/normalize/reuse/{model}/{locale}/{timestamp}` |
15
+ | Branch pattern | `cr/normalize/extract/{domain}/{timestamp}` | `cr/normalize/reuse/{model}/{locale}/{timestamp}` |
16
16
  | Prerequisite | Initialized `.contentrain/` | Completed extraction (content exists) |
17
17
  | Workflow mode | Always `review` | Always `review` |
18
18
  | Standalone value | Yes — content is manageable in Studio immediately | Depends on Phase 1 |
@@ -2,14 +2,14 @@
2
2
 
3
3
  > **Prerequisites:** Read `prompts/common.md` first. All shared rules apply.
4
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.
5
+ This mode is for reviewing content changes on pending `cr/*` branches before they are merged. You act as a content quality reviewer, applying all Contentrain rules systematically.
6
6
 
7
7
  ---
8
8
 
9
9
  ## Pipeline
10
10
 
11
11
  ```
12
- Step 1: List open contentrain/* branches
12
+ Step 1: List open cr/* branches
13
13
  Step 2: Show diffs for selected branch
14
14
  Step 3: Apply review checklist
15
15
  Step 4: Recommend action
@@ -19,19 +19,19 @@ Step 4: Recommend action
19
19
 
20
20
  ## Step 1: List Pending Branches
21
21
 
22
- Call `contentrain_status` to see pending changes and open branches. Identify branches with the `contentrain/` prefix that are awaiting review.
22
+ Call `contentrain_status` to see pending changes and open branches. Identify branches with the `cr/` prefix that are awaiting review.
23
23
 
24
24
  Branch naming convention:
25
25
  ```
26
- contentrain/{operation}/{model}/{locale}/{timestamp}
26
+ cr/{operation}/{model}/{locale}/{timestamp}
27
27
  ```
28
28
 
29
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
30
+ - `cr/content/...` — content updates
31
+ - `cr/model/...` — model changes
32
+ - `cr/normalize/extract/...` — normalize extraction
33
+ - `cr/normalize/reuse/...` — normalize reuse (source patching)
34
+ - `cr/new/scaffold-...` — scaffold operations
35
35
 
36
36
  ---
37
37
 
@@ -156,7 +156,8 @@ Each entry in the `entries` array has this shape:
156
156
  | Tool | Purpose | Parameters |
157
157
  |------|---------|------------|
158
158
  | `contentrain_validate` | Validate project content against model schemas | `model?`, `fix?` (bool) |
159
- | `contentrain_submit` | Push contentrain/* branches to remote | `branches?` (string[]), `message?` |
159
+ | `contentrain_submit` | Push `cr/*` branches to the remote | `branches?` (string[]), `message?` |
160
+ | `contentrain_merge` | Merge a review-mode branch into `contentrain` and fast-forward the base | `branch`, `confirm: true` |
160
161
 
161
162
  ### 2.7 Bulk Tools
162
163
 
@@ -184,9 +185,15 @@ Each entry in the `entries` array has this shape:
184
185
 
185
186
  #### contentrain_submit parameters
186
187
 
187
- - `branches`: specific branch names to push (omit for all contentrain/* branches).
188
+ - `branches`: specific branch names to push (omit for all `cr/*` branches).
188
189
  - `message`: optional message for the push operation.
189
190
 
191
+ #### contentrain_merge parameters
192
+
193
+ - `branch`: feature branch to merge (e.g. `cr/content/blog/...`).
194
+ - `confirm`: must be `true` to execute.
195
+ - Local-only: MCP runs the merge through a worktree + `update-ref` + selective sync. Use it when the workflow is `review` and the change has been approved.
196
+
190
197
  ---
191
198
 
192
199
  ## 3. Calling Sequences (Pipelines)
@@ -287,7 +294,7 @@ contentrain_apply(mode: "reuse", scope: {model: "model-id"}, dry_run: true) (pre
287
294
 
288
295
  - A dedicated `contentrain` branch is the single source of truth for content state, created at init and protected from deletion.
289
296
  - Every write operation creates a temporary worktree on a new feature branch forked from `contentrain`.
290
- - Branch naming: `contentrain/{operation}/{model}/{timestamp}` (locale included when applicable).
297
+ - Branch naming: `cr/{operation}/{model}[/{locale}]/{timestamp}-{suffix}` (locale included when applicable; legacy `contentrain/*` branches are auto-migrated on first init).
291
298
  - You do not create branches manually. MCP handles Git transactions.
292
299
  - Developer's working tree is never mutated during MCP operations (no stash, no checkout, no merge on the developer's tree).
293
300
  - context.json is committed together with content changes, not as a separate commit.
@@ -297,9 +304,35 @@ contentrain_apply(mode: "reuse", scope: {model: "model-id"}, dry_run: true) (pre
297
304
  ### 4.7 Branch Health
298
305
 
299
306
  - MCP enforces branch health limits: 50+ active branches triggers a warning, 80+ blocks new write operations.
300
- - If blocked, merge or delete old `contentrain/*` branches before proceeding.
307
+ - If blocked, merge or delete old `cr/*` branches before proceeding.
301
308
  - `contentrain_status` reports branch health automatically.
302
309
 
310
+ ### 4.8 Transport and Provider Capabilities
311
+
312
+ MCP runs over three transports / provider combinations: **LocalProvider** (stdio or HTTP), **GitHubProvider** (HTTP only), and **GitLabProvider** (HTTP only). Each provider advertises a capability set that gates which tools are available.
313
+
314
+ | Capability | Local | GitHub | GitLab | Tools affected |
315
+ |---|---|---|---|---|
316
+ | `localWorktree` | ✓ | — | — | `init`, `scaffold`, `validate --fix`, `submit`, `merge`, `bulk` |
317
+ | `sourceRead` | ✓ | — | — | `apply` (extract mode) |
318
+ | `sourceWrite` | ✓ | — | — | `apply` (reuse mode) |
319
+ | `astScan` | ✓ | — | — | `scan` |
320
+ | `pushRemote` | ✓ | ✓ | ✓ | `submit` |
321
+ | `branchProtection` | — | ✓ | ✓ | merge fallback detection |
322
+ | `pullRequestFallback` | — | ✓ | ✓ | merge fallback creation |
323
+
324
+ When a tool is called on a provider that lacks the required capability, MCP returns a uniform error:
325
+
326
+ ```json
327
+ {
328
+ "error": "contentrain_scan requires local filesystem access.",
329
+ "capability_required": "astScan",
330
+ "hint": "This tool is unavailable when MCP is driven by a remote provider. Use a LocalProvider or the stdio transport."
331
+ }
332
+ ```
333
+
334
+ If the agent is driving a remote-only session (e.g. Studio-hosted MCP over HTTP + GitHubProvider), normalize and other local-only tools must run in a separate local checkout before content is pushed.
335
+
303
336
  ---
304
337
 
305
338
  ## 5. Tool Details
@@ -401,7 +434,8 @@ Keep suggestions brief and contextual. Do not repeat them if already mentioned.
401
434
  | `VALIDATION_FAILED` | Content does not match schema | Fix errors reported by `contentrain_validate`, then retry |
402
435
  | `REFERENCED_MODEL` | Attempting to delete a model referenced by others | Remove relation fields from referencing models first |
403
436
  | `LOCALE_MISMATCH` | Locale not in supported list | Check `config.locales.supported`, add locale or use a supported one |
404
- | `BRANCH_BLOCKED` | Too many active contentrain/* branches (80+) | Merge or delete old branches before creating new ones |
437
+ | `BRANCH_BLOCKED` | Too many active `cr/*` branches (80+) | Merge or delete old branches before creating new ones |
438
+ | `capability_required` | Tool requires a capability the active provider does not expose (e.g. `astScan` on a GitHubProvider) | Switch to a LocalProvider session, or run the tool in a local checkout before returning to the remote flow |
405
439
 
406
440
  ### Rule: Always Check Status After Errors
407
441
 
@@ -22,7 +22,7 @@ Each phase produces a separate branch for independent review. This separation en
22
22
  | Purpose | Pull content from source to `.contentrain/` | Patch source files with content references |
23
23
  | Scope | Full project scan | Per model or per domain |
24
24
  | Source files modified | No | Yes |
25
- | Branch pattern | `contentrain/normalize/extract/{domain}/{timestamp}` | `contentrain/normalize/reuse/{model}/{locale}/{timestamp}` |
25
+ | Branch pattern | `cr/normalize/extract/{domain}/{timestamp}-{suffix}` | `cr/normalize/reuse/{model}/{locale}/{timestamp}-{suffix}` |
26
26
  | Prerequisite | Initialized `.contentrain/` | Completed extraction (content exists in `.contentrain/`) |
27
27
  | Workflow mode | Always `review` | Always `review` |
28
28
  | Standalone value | Yes -- content is manageable in Studio immediately | Depends on Phase 1 |
@@ -43,25 +43,26 @@ Contentrain supports two workflow modes, configured in `.contentrain/config.json
43
43
  All Contentrain branches follow a strict naming pattern:
44
44
 
45
45
  ```
46
- contentrain/{operation}/{model}/{locale}/{timestamp}
46
+ cr/{operation}/{model}/{locale}/{timestamp}
47
47
  ```
48
48
 
49
49
  ### Examples
50
50
 
51
51
  | Scenario | Branch Name |
52
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` |
53
+ | Content update | `cr/content/blog-post/en/1710300000-a1b2` |
54
+ | Model creation | `cr/model/team-member/1710300000-c3d4` |
55
+ | Normalize extraction | `cr/normalize/extract/blog/1710300000-e5f6` |
56
+ | Normalize reuse | `cr/normalize/reuse/marketing-hero/en/1710300000-0789` |
57
+ | Scaffold | `cr/new/scaffold-landing/en/1710300000-1234` |
58
58
 
59
59
  ### Rules
60
60
 
61
61
  - Branches are created automatically by MCP tools. Do NOT create them manually.
62
- - The `{timestamp}` component ensures uniqueness.
62
+ - The `{timestamp}-{suffix}` component ensures uniqueness across concurrent writes.
63
63
  - `{locale}` is included when the operation is locale-specific.
64
64
  - `{model}` is included when the operation targets a specific model.
65
+ - Legacy `contentrain/*` branches from pre-`cr/*` installations are auto-migrated on first init.
65
66
 
66
67
  ---
67
68