@contentrain/rules 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -31
- package/dist/index.cjs +3 -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 +3 -1
- package/dist/index.mjs.map +1 -1
- package/essential/contentrain-essentials.md +10 -2
- package/package.json +5 -2
- package/prompts/normalize-mode.md +1 -1
- package/prompts/review-mode.md +9 -9
- package/shared/accessibility-rules.md +155 -0
- package/shared/content-conventions.md +314 -0
- package/shared/content-quality.md +294 -0
- package/shared/i18n-quality.md +293 -0
- package/shared/mcp-usage.md +442 -0
- package/shared/media-rules.md +165 -0
- package/shared/normalize-rules.md +335 -0
- package/shared/schema-rules.md +380 -0
- package/shared/security-rules.md +141 -0
- package/shared/seo-rules.md +224 -0
- package/shared/workflow-rules.md +318 -0
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,9 @@ const MCP_TOOLS = [
|
|
|
55
55
|
"contentrain_apply",
|
|
56
56
|
"contentrain_validate",
|
|
57
57
|
"contentrain_submit",
|
|
58
|
-
"
|
|
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"];
|
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,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"];
|
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,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
|
-
"
|
|
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 = [
|
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 (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 (`
|
|
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
|
+
"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",
|
|
@@ -39,12 +39,14 @@
|
|
|
39
39
|
"default": "./dist/index.mjs"
|
|
40
40
|
},
|
|
41
41
|
"./essential/*": "./essential/*",
|
|
42
|
+
"./shared/*": "./shared/*",
|
|
42
43
|
"./prompts/*": "./prompts/*",
|
|
43
44
|
"./context/*": "./context/*"
|
|
44
45
|
},
|
|
45
46
|
"files": [
|
|
46
47
|
"dist",
|
|
47
48
|
"essential",
|
|
49
|
+
"shared",
|
|
48
50
|
"prompts",
|
|
49
51
|
"context"
|
|
50
52
|
],
|
|
@@ -52,7 +54,8 @@
|
|
|
52
54
|
"@types/node": "^22.0.0",
|
|
53
55
|
"tsdown": "^0.21.0",
|
|
54
56
|
"typescript": "^5.7.0",
|
|
55
|
-
"vitest": "^3.0.0"
|
|
57
|
+
"vitest": "^3.0.0",
|
|
58
|
+
"@contentrain/mcp": "1.3.0"
|
|
56
59
|
},
|
|
57
60
|
"scripts": {
|
|
58
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
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Accessibility Rules
|
|
2
|
+
|
|
3
|
+
These rules are MANDATORY for all AI agents creating or editing content in Contentrain projects.
|
|
4
|
+
Violations will be flagged during validation. No exceptions unless explicitly overridden by `context.json` configuration.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Image Accessibility
|
|
9
|
+
|
|
10
|
+
1. Every `image` type field MUST have a corresponding alt text value. If the model defines an `image_alt` field, populate it. If not, include alt text guidance in the image field's `description` metadata.
|
|
11
|
+
|
|
12
|
+
2. Alt text MUST describe the image's **content and function**, not its appearance.
|
|
13
|
+
- GOOD: `"CEO Jane Doe speaking at the 2024 product launch"`
|
|
14
|
+
- BAD: `"A photo with blue tones and a person on stage"`
|
|
15
|
+
|
|
16
|
+
3. Decorative images (visual separators, background textures) MUST have alt text set to an empty string `""`. Never leave alt text undefined or null — explicitly set it to `""`.
|
|
17
|
+
|
|
18
|
+
4. Complex images (charts, infographics, diagrams) MUST have a short alt text summarizing the conclusion, plus a detailed description in an adjacent text field or in the body content.
|
|
19
|
+
- Example alt: `"Bar chart showing Q3 revenue grew 22% year-over-year"`
|
|
20
|
+
- Example adjacent text: full data table or written summary
|
|
21
|
+
|
|
22
|
+
5. Alt text MUST NOT exceed **125 characters**. Screen readers may truncate longer text.
|
|
23
|
+
|
|
24
|
+
6. Icon images used as interactive elements MUST have alt text describing the **action**, not the icon.
|
|
25
|
+
- GOOD: `"Search"`, `"Close menu"`, `"Open settings"`
|
|
26
|
+
- BAD: `"Magnifying glass icon"`, `"X icon"`
|
|
27
|
+
|
|
28
|
+
7. Do not begin alt text with "Image of" or "Photo of" — the screen reader already announces it as an image.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Language & Readability
|
|
33
|
+
|
|
34
|
+
1. Target a **grade 8-10 reading level** (Flesch-Kincaid) for general content.
|
|
35
|
+
|
|
36
|
+
2. Target **grade 6-8** for public-facing critical content: legal notices, safety information, error messages, onboarding flows.
|
|
37
|
+
|
|
38
|
+
3. Use plain language. Prefer common words over formal synonyms:
|
|
39
|
+
- "use" not "utilize"
|
|
40
|
+
- "start" not "commence"
|
|
41
|
+
- "help" not "facilitate"
|
|
42
|
+
- "buy" not "purchase"
|
|
43
|
+
- "end" not "terminate"
|
|
44
|
+
|
|
45
|
+
4. Define every acronym and abbreviation on first use: `"Content Management System (CMS)"`. After the first definition, use the acronym freely.
|
|
46
|
+
|
|
47
|
+
5. Do not use jargon unless the content targets a technical audience. Check `context.json > tone` to determine the audience. When `tone` is `"technical"`, domain-specific terms are acceptable without definitions.
|
|
48
|
+
|
|
49
|
+
6. Keep sentences short: **15-20 words average**. Break long sentences at natural clause boundaries.
|
|
50
|
+
|
|
51
|
+
7. Keep paragraphs short: **3-5 sentences maximum**. Use line breaks between paragraphs.
|
|
52
|
+
|
|
53
|
+
8. Use active voice. Passive voice is acceptable only when the actor is unknown or irrelevant.
|
|
54
|
+
- GOOD: `"The system saves your changes automatically."`
|
|
55
|
+
- BAD: `"Your changes are saved automatically by the system."`
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Link Text
|
|
60
|
+
|
|
61
|
+
1. Link text MUST be descriptive and self-explanatory. It must make sense **out of context** because screen readers present links in an isolated list.
|
|
62
|
+
- GOOD: `"Download the 2024 Annual Report"`
|
|
63
|
+
- BAD: `"Click here"`
|
|
64
|
+
|
|
65
|
+
2. NEVER use these as standalone link text: `"click here"`, `"read more"`, `"learn more"`, `"here"`, `"link"`, `"this"`.
|
|
66
|
+
|
|
67
|
+
3. For file downloads, include the file type and size in the link text:
|
|
68
|
+
- `"Download the Q3 Budget (PDF, 2.4 MB)"`
|
|
69
|
+
|
|
70
|
+
4. Do not use the raw URL as link text unless the content is specifically listing URLs.
|
|
71
|
+
|
|
72
|
+
5. Keep link text concise — describe the destination or action in 2-8 words.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Heading Semantics
|
|
77
|
+
|
|
78
|
+
1. Headings MUST describe the content of their section. Never use headings purely for visual styling (font size, bold).
|
|
79
|
+
|
|
80
|
+
2. Heading levels MUST reflect **document hierarchy**:
|
|
81
|
+
- `h2` for top-level sections within the page
|
|
82
|
+
- `h3` for subsections of an `h2`
|
|
83
|
+
- `h4` for subsections of an `h3`
|
|
84
|
+
- Never skip levels (e.g., `h2` directly to `h4`)
|
|
85
|
+
|
|
86
|
+
3. Every distinct content section SHOULD have a heading.
|
|
87
|
+
|
|
88
|
+
4. Headings MUST NOT be empty or contain only whitespace.
|
|
89
|
+
|
|
90
|
+
5. Do not duplicate heading text within the same page unless sections are genuinely distinct (e.g., "Overview" under two different parent headings is acceptable).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Content Structure
|
|
95
|
+
|
|
96
|
+
1. Use **semantic markup** appropriate to the content type:
|
|
97
|
+
- Unordered lists (`ul`) for items without sequence
|
|
98
|
+
- Ordered lists (`ol`) for steps or ranked items
|
|
99
|
+
- Headings for section titles
|
|
100
|
+
- Paragraphs for body text
|
|
101
|
+
- Blockquotes for quoted material
|
|
102
|
+
|
|
103
|
+
2. Tables MUST include a header row or header column. Keep table structure simple — avoid merged cells and nested tables.
|
|
104
|
+
|
|
105
|
+
3. Provide a text alternative for every piece of non-text content (images, charts, embedded media).
|
|
106
|
+
|
|
107
|
+
4. Sequential content (steps, instructions, timelines) MUST follow logical reading order. Do not rely on CSS or layout to reorder content.
|
|
108
|
+
|
|
109
|
+
5. Lists MUST have at least two items. A single-item list should be rewritten as a paragraph or inline text.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Color & Visual References
|
|
114
|
+
|
|
115
|
+
1. NEVER use color alone to convey meaning.
|
|
116
|
+
- BAD: `"Required fields are highlighted in red."`
|
|
117
|
+
- GOOD: `"Required fields are marked with an asterisk (*)."`
|
|
118
|
+
|
|
119
|
+
2. Do not reference visual position in content text.
|
|
120
|
+
- BAD: `"Click the button on the right."`
|
|
121
|
+
- GOOD: `"Click the Submit button."`
|
|
122
|
+
|
|
123
|
+
3. Ensure all text content is meaningful without any visual context. Content must be understandable when read aloud or rendered in plain text.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Error Messages & Forms
|
|
128
|
+
|
|
129
|
+
1. Error messages MUST identify **which field** has the error.
|
|
130
|
+
|
|
131
|
+
2. Error messages MUST describe **what the error is** and how to fix it.
|
|
132
|
+
- GOOD: `"Enter a valid email address (e.g., name@example.com)."`
|
|
133
|
+
- BAD: `"Invalid input."`
|
|
134
|
+
|
|
135
|
+
3. Use **positive framing** — tell the user what to do, not what they did wrong.
|
|
136
|
+
- GOOD: `"Enter a date in YYYY-MM-DD format."`
|
|
137
|
+
- BAD: `"Wrong date format."`
|
|
138
|
+
|
|
139
|
+
4. Group related form fields with descriptive labels. Every input field MUST have a label.
|
|
140
|
+
|
|
141
|
+
5. Do not use placeholder text as a substitute for labels.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Multimedia
|
|
146
|
+
|
|
147
|
+
1. Video content MUST reference a transcript — either as inline content, a URL, or a relation to a document entry.
|
|
148
|
+
|
|
149
|
+
2. Audio content MUST have a text transcript available.
|
|
150
|
+
|
|
151
|
+
3. If content auto-plays, note this in metadata so the frontend can provide pause/stop controls. Auto-playing media with audio is strongly discouraged.
|
|
152
|
+
|
|
153
|
+
4. Time-based media (video, audio, animations) MUST include duration information when the model supports it.
|
|
154
|
+
|
|
155
|
+
5. Animated content (GIFs, auto-playing videos) should be flagged if longer than 5 seconds — provide a mechanism to pause.
|