@contentrain/rules 0.5.2 → 0.6.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
@@ -44,7 +44,7 @@ Published under `shared/` — detailed standards per domain:
44
44
  - `content-quality.md` — structure, required fields, content completeness
45
45
  - `seo-rules.md` — meta optimization, keywords, canonical URLs
46
46
  - `accessibility-rules.md` — alt text, ARIA labels, color contrast
47
- - `media-rules.md` — image optimization, responsive sizing, asset naming
47
+ - `media-rules.md` — storage models (local-file vs Studio-CDN delivery), image optimization, responsive sizing, asset naming
48
48
  - `schema-rules.md` — model design, field types, relations, inheritance
49
49
  - `i18n-quality.md` — translation completeness, locale parity
50
50
  - `security-rules.md` — sensitive data patterns, secret detection, XSS prevention
@@ -75,7 +75,7 @@ The package root exports constants for tooling:
75
75
 
76
76
  - `FIELD_TYPES` — 27 flat field types
77
77
  - `MODEL_KINDS` — `singleton`, `collection`, `document`, `dictionary`
78
- - `MCP_TOOLS` — 17 MCP tool names (includes `contentrain_merge` and `contentrain_doctor`)
78
+ - `MCP_TOOLS` — 24 MCP tool names: 19 core + 5 media (`contentrain_media_*`, registered only on media-capable providers)
79
79
  - `ESSENTIAL_RULES_FILE` — path to essential guardrails markdown
80
80
  - `STACKS` — supported framework stacks
81
81
 
@@ -84,7 +84,7 @@ The package root exports constants for tooling:
84
84
  ```ts
85
85
  import { MCP_TOOLS, ESSENTIAL_RULES_FILE, FIELD_TYPES } from '@contentrain/rules'
86
86
 
87
- console.log(MCP_TOOLS.length) // 17
87
+ console.log(MCP_TOOLS.length) // 24
88
88
  console.log(MCP_TOOLS.includes('contentrain_merge')) // true
89
89
  console.log(MCP_TOOLS.includes('contentrain_doctor')) // true
90
90
  console.log(ESSENTIAL_RULES_FILE) // 'essential/contentrain-essentials.md'
package/dist/index.cjs CHANGED
@@ -59,7 +59,12 @@ const MCP_TOOLS = [
59
59
  "contentrain_branch_list",
60
60
  "contentrain_branch_delete",
61
61
  "contentrain_bulk",
62
- "contentrain_doctor"
62
+ "contentrain_doctor",
63
+ "contentrain_media_list",
64
+ "contentrain_media_get",
65
+ "contentrain_media_ingest",
66
+ "contentrain_media_update",
67
+ "contentrain_media_delete"
63
68
  ];
64
69
  const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
65
70
  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_merge", "contentrain_branch_list", "contentrain_branch_delete", "contentrain_bulk", "contentrain_doctor"];
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", "contentrain_media_list", "contentrain_media_get", "contentrain_media_ingest", "contentrain_media_update", "contentrain_media_delete"];
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,KAaD,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,KAiBD,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_merge", "contentrain_branch_list", "contentrain_branch_delete", "contentrain_bulk", "contentrain_doctor"];
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", "contentrain_media_list", "contentrain_media_get", "contentrain_media_ingest", "contentrain_media_update", "contentrain_media_delete"];
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,KAaD,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,KAiBD,OAAA,WAAkB,SAAA;AAAA,cAIjB,oBAAA;AAAA,cAIA,MAAA;AAAA,KACD,KAAA,WAAgB,MAAA"}
package/dist/index.mjs CHANGED
@@ -58,7 +58,12 @@ const MCP_TOOLS = [
58
58
  "contentrain_branch_list",
59
59
  "contentrain_branch_delete",
60
60
  "contentrain_bulk",
61
- "contentrain_doctor"
61
+ "contentrain_doctor",
62
+ "contentrain_media_list",
63
+ "contentrain_media_get",
64
+ "contentrain_media_ingest",
65
+ "contentrain_media_update",
66
+ "contentrain_media_delete"
62
67
  ];
63
68
  const ESSENTIAL_RULES_FILE = "essential/contentrain-essentials.md";
64
69
  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 (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"}
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 (24 tools: 19 core + 5 media) ───\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 // Media tools — registered only when the provider exposes a media stack\n // (Studio MCP Cloud); absent from local stdio servers.\n 'contentrain_media_list', 'contentrain_media_get', 'contentrain_media_ingest',\n 'contentrain_media_update', 'contentrain_media_delete',\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;CAGA;CAA0B;CAAyB;CACnD;CAA4B;CAC7B;AAMD,MAAa,uBAAuB;AAIpC,MAAa,SAAS;CAAC;CAAQ;CAAQ;CAAS;CAAa;CAAS;CAAO"}
@@ -57,6 +57,13 @@ MCP is **deterministic infrastructure**. The agent (you) is the **intelligence l
57
57
  | `contentrain_branch_delete` | Delete a stale/failed `cr/*` branch (the contentrain branch is protected) |
58
58
  | `contentrain_bulk` | Batch operations (copy_locale/update_status/delete_entries) |
59
59
  | `contentrain_doctor` | Project health report (env + structure + orphan content + branch pressure + SDK freshness) |
60
+ | `contentrain_media_list` | List media assets (media-capable providers only, e.g. Studio MCP Cloud) |
61
+ | `contentrain_media_get` | Get one media asset by id |
62
+ | `contentrain_media_ingest` | Ingest an asset from a source URL (provider fetches server-side) |
63
+ | `contentrain_media_update` | Update asset metadata (alt/tags/filename) |
64
+ | `contentrain_media_delete` | Delete an asset (references in content are NOT rewritten) |
65
+
66
+ Media tools appear only when the provider exposes a media stack; discover paths with `contentrain_media_list`, then reference them in media/image/file fields via `contentrain_content_save`.
60
67
 
61
68
  ## Mandatory Protocols
62
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contentrain/rules",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "license": "MIT",
5
5
  "description": "AI agent rules for Contentrain — quality standards, architecture conventions, IDE integration",
6
6
  "type": "module",
@@ -55,7 +55,7 @@
55
55
  "tsdown": "^0.21.0",
56
56
  "typescript": "^5.7.0",
57
57
  "vitest": "^3.0.0",
58
- "@contentrain/mcp": "1.5.2"
58
+ "@contentrain/mcp": "1.10.0"
59
59
  },
60
60
  "scripts": {
61
61
  "build": "tsdown src/index.ts --format esm,cjs --dts",
@@ -5,6 +5,18 @@ Follow these guidelines when populating image, video, or file fields in any cont
5
5
 
6
6
  ---
7
7
 
8
+ ## Storage & Reference Models
9
+
10
+ Media references are stored in one of two models. Identify which one the project uses before populating image, video, or file fields. The asset rules below (dimensions, formats, size limits, naming) apply to **both**; only the **Asset Organization** section (paths under `assets_path`, relative references) is specific to the local-file model.
11
+
12
+ 1. **Local file model (default / OSS).** Media lives on disk under `config.json > assets_path` (default `.contentrain/assets/`) and is referenced by a **relative path from the project root** (e.g. `.contentrain/assets/blog/hero.webp`). To turn relative paths into URLs at read time, set `config.json > cdn.url` (or `contentrain generate --cdnBaseUrl <base>`) and use the `media()` resolver baked into the `@contentrain/query` generated client — `media('media/...') → {cdn.url}/{path}`.
13
+
14
+ 2. **Studio CDN model.** Media lives in the Studio CDN/object store and is referenced by a relative storage path (`media/...`) returned by the media library. Pass either that `media/...` path or its URL to `contentrain_content_save`: in **cloud mode** the value is **automatically normalized to an absolute public delivery URL** on save (`{base}/{path}`), in both media fields and markdown bodies, so the committed content renders in a browser anywhere with no SDK. In **local mode** the relative path is kept verbatim. The rewrite is idempotent and never touches external URLs (`http(s)://`, `//`, `data:`) or already-absolute delivery URLs — so for external images (a CDN or Unsplash URL), just save the URL directly.
15
+
16
+ Never hand-build delivery URLs or guess the CDN base. Save the path or URL the media library gives you; the platform resolves it.
17
+
18
+ ---
19
+
8
20
  ## Image Dimensions (Recommended)
9
21
 
10
22
  1. Use these standard dimensions unless the project's `context.json` specifies overrides: