@contentrain/rules 0.3.3 → 0.5.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 +61 -31
- package/dist/index.cjs +5 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -1
- package/dist/index.mjs.map +1 -1
- package/essential/contentrain-essentials.md +13 -3
- package/package.json +3 -2
- package/prompts/normalize-mode.md +1 -1
- package/prompts/review-mode.md +9 -9
- package/shared/mcp-usage.md +39 -5
- package/shared/normalize-rules.md +1 -1
- package/shared/workflow-rules.md +8 -7
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
|
|
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
|
|
74
|
+
The package root exports constants for tooling:
|
|
57
75
|
|
|
58
76
|
- `FIELD_TYPES` — 27 flat field types
|
|
59
|
-
- `MODEL_KINDS` — singleton
|
|
60
|
-
- `MCP_TOOLS` —
|
|
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.
|
|
70
|
-
console.log(
|
|
71
|
-
console.log(
|
|
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
|
-
|
|
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
|
-
-
|
|
81
|
-
-
|
|
82
|
-
-
|
|
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
|
-
|
|
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`
|
|
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` =
|
|
97
|
-
- `skills` =
|
|
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
|
|
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,11 @@ const MCP_TOOLS = [
|
|
|
55
55
|
"contentrain_apply",
|
|
56
56
|
"contentrain_validate",
|
|
57
57
|
"contentrain_submit",
|
|
58
|
-
"
|
|
58
|
+
"contentrain_merge",
|
|
59
|
+
"contentrain_branch_list",
|
|
60
|
+
"contentrain_branch_delete",
|
|
61
|
+
"contentrain_bulk",
|
|
62
|
+
"contentrain_doctor"
|
|
59
63
|
];
|
|
60
64
|
const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
|
|
61
65
|
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_branch_list", "contentrain_branch_delete", "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"];
|
package/dist/index.d.cts.map
CHANGED
|
@@ -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,
|
|
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,KAaD,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_branch_list", "contentrain_branch_delete", "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"];
|
package/dist/index.d.mts.map
CHANGED
|
@@ -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,
|
|
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,KAaD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -54,7 +54,11 @@ const MCP_TOOLS = [
|
|
|
54
54
|
"contentrain_apply",
|
|
55
55
|
"contentrain_validate",
|
|
56
56
|
"contentrain_submit",
|
|
57
|
-
"
|
|
57
|
+
"contentrain_merge",
|
|
58
|
+
"contentrain_branch_list",
|
|
59
|
+
"contentrain_branch_delete",
|
|
60
|
+
"contentrain_bulk",
|
|
61
|
+
"contentrain_doctor"
|
|
58
62
|
];
|
|
59
63
|
const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
|
|
60
64
|
const STACKS = [
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 (
|
|
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 (19 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_branch_list', 'contentrain_branch_delete',\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;CAA2B;CAC3B;CACA;CACD;AAMD,MAAa,uBAAuB;AAIpC,MAAa,SAAS;CAAC;CAAQ;CAAQ;CAAS;CAAa;CAAS;CAAO"}
|
|
@@ -52,8 +52,11 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
|
|
|
52
52
|
| `contentrain_apply` | Apply normalize (extract/reuse) |
|
|
53
53
|
| `contentrain_validate` | Validate content against schemas |
|
|
54
54
|
| `contentrain_submit` | Push branches to remote |
|
|
55
|
-
| `contentrain_merge` | Merge a review-mode branch into contentrain locally |
|
|
55
|
+
| `contentrain_merge` | Merge a review-mode branch into contentrain locally (by exact branch or model) |
|
|
56
|
+
| `contentrain_branch_list` | List pending `cr/*` branches + merge status |
|
|
57
|
+
| `contentrain_branch_delete` | Delete a stale/failed `cr/*` branch (the contentrain branch is protected) |
|
|
56
58
|
| `contentrain_bulk` | Batch operations (copy_locale/update_status/delete_entries) |
|
|
59
|
+
| `contentrain_doctor` | Project health report (env + structure + orphan content + branch pressure + SDK freshness) |
|
|
57
60
|
|
|
58
61
|
## Mandatory Protocols
|
|
59
62
|
|
|
@@ -68,7 +71,7 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
|
|
|
68
71
|
|
|
69
72
|
- A dedicated `contentrain` branch is the single source of truth for content state, created at init
|
|
70
73
|
- Every write operation creates a temporary worktree on the `contentrain` branch automatically
|
|
71
|
-
- Feature branches (`
|
|
74
|
+
- Feature branches (`cr/{operation}/{model}/{locale}/{timestamp}`) are created from `contentrain` for each operation
|
|
72
75
|
- **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
76
|
- **review** mode: feature branch pushed to remote for team review
|
|
74
77
|
- Developer's working tree is never mutated during MCP git operations (no stash, no checkout, no merge on the developer's tree)
|
|
@@ -76,7 +79,7 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
|
|
|
76
79
|
- The `contentrain` branch is protected from deletion
|
|
77
80
|
- context.json is committed together with content changes, not as a separate commit
|
|
78
81
|
- Never create branches manually, never commit directly to main or the `contentrain` branch
|
|
79
|
-
- 50+ active branches = warning, 80+ = blocked
|
|
82
|
+
- 50+ active `cr/*` branches = warning, 80+ = blocked
|
|
80
83
|
|
|
81
84
|
## CLI Serve — Review & Approval
|
|
82
85
|
|
|
@@ -111,6 +114,13 @@ This regenerates `.contentrain/client/` — required for `#contentrain` imports
|
|
|
111
114
|
- Collection entry IDs and dictionary keys must match across all locales
|
|
112
115
|
- IDs and slugs are locale-agnostic — same reference works everywhere
|
|
113
116
|
|
|
117
|
+
## Content Governance
|
|
118
|
+
|
|
119
|
+
- **No duplicate values** — before creating a dictionary key, check if the value already exists under another key (MCP warns automatically via advisories)
|
|
120
|
+
- **Vocabulary first** — check `.contentrain/vocabulary.json` for canonical terms before creating content. Use approved terms exactly, do not invent synonyms
|
|
121
|
+
- **Run validation** — after bulk content operations, call `contentrain_validate` to catch duplicate values, missing translations, and schema issues
|
|
122
|
+
- **Periodic health check** — run `contentrain doctor --usage` to detect unused keys, duplicate values, and locale coverage gaps
|
|
123
|
+
|
|
114
124
|
## Security
|
|
115
125
|
|
|
116
126
|
- 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
|
+
"version": "0.5.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.5.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 | `
|
|
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 |
|
package/prompts/review-mode.md
CHANGED
|
@@ -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 `
|
|
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
|
|
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 `
|
|
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
|
-
|
|
26
|
+
cr/{operation}/{model}/{locale}/{timestamp}
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
Common branch types:
|
|
30
|
-
- `
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
- `
|
|
34
|
-
- `
|
|
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
|
|
package/shared/mcp-usage.md
CHANGED
|
@@ -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
|
|
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
|
|
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: `
|
|
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 `
|
|
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
|
|
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 | `
|
|
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 |
|
package/shared/workflow-rules.md
CHANGED
|
@@ -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
|
-
|
|
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 | `
|
|
54
|
-
| Model creation | `
|
|
55
|
-
| Normalize extraction | `
|
|
56
|
-
| Normalize reuse | `
|
|
57
|
-
| Scaffold | `
|
|
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
|
|