fragments/policy
coreCreate and manage Fragments design policies from natural language descriptions. Use when the user wants to create a design rule, add a policy, enforce a convention, or customize governance checks.
Fragments Policy
Create and manage custom design policies that Fragments enforces during governance checks.
Prerequisites
- @fragments-sdk/govern and @fragments-sdk/cli must be installed. If not, run /fragments-cloud-setup first.
- A fragments.config.ts must exist. Ensure it includes a policies glob:
import { defineConfig } from '@fragments-sdk/govern';
export default defineConfig({
cloud: true,
checks: ['accessibility', 'consistency', 'responsive'],
policies: ['./.fragments/policies/*.ts'],
input: './src/**/*.{tsx,jsx}',
});
Modes
Parse $ARGUMENTS to determine the mode:
- create (default): Create a new policy from a natural language description
- list: Show all active policies
- edit: Modify an existing policy
- delete: Remove a policy
Create mode
-
Take the user's natural language description.
-
Generate a policy file in .fragments/policies/. Here are examples covering common categories:
Touch target enforcement:
// .fragments/policies/min-button-height.ts
import { definePolicy } from '@fragments-sdk/govern';
export default definePolicy({
name: 'min-button-height',
description: 'All buttons must have a minimum height of 44px for touch targets',
severity: 'error',
check({ node, report }) {
if (node.type === 'button' || node.role === 'button') {
const height = node.computedStyles?.height;
if (height && parseFloat(height) < 44) {
report({
message: `Button height is ${height} but minimum is 44px`,
fix: { property: 'minHeight', value: '44px' },
});
}
}
},
});
Design token enforcement:
// .fragments/policies/no-hardcoded-colors.ts
import { definePolicy } from '@fragments-sdk/govern';
export default definePolicy({
name: 'no-hardcoded-colors',
description: 'Colors must use design tokens, not raw hex/rgb values',
severity: 'warning',
check({ node, report }) {
const colorProps = ['color', 'backgroundColor', 'borderColor'];
for (const prop of colorProps) {
const value = node.styles?.[prop];
if (value && /^(#|rgb|hsl)/.test(value)) {
report({
message: `Hardcoded color "${value}" on "${prop}" -- use a design token instead`,
fix: { property: prop, value: 'var(--fui-text-primary)' },
});
}
}
},
});
Structural accessibility:
// .fragments/policies/single-h1.ts
import { definePolicy } from '@fragments-sdk/govern';
export default definePolicy({
name: 'single-h1',
description: 'Each page must have exactly one h1 element',
severity: 'error',
check({ node, context, report }) {
if (node.tag === 'h1') {
context.h1Count = (context.h1Count || 0) + 1;
if (context.h1Count > 1) {
report({
message: `Multiple h1 elements found (this is #${context.h1Count}). Use h2-h6 for subheadings.`,
});
}
}
},
});
- Register the policy -- ensure fragments.config.ts has a policies glob that matches the new file path.
- Run a check to validate: npx fragments govern check --cloud
- Show results and ask if the policy needs adjustment.
List mode
npx fragments govern policies list
If the CLI subcommand is not available, read all files in .fragments/policies/ directly and display: policy name, description, severity, status (active/disabled).
Edit mode
- If no policy name is specified, show the list first.
- Read the target policy file in .fragments/policies/.
- Let the user describe the change in natural language.
- Update the policy file and re-run checks to validate:
sh
npx fragments govern check --cloud
Delete mode
- If no policy name is specified, show the list first.
- Confirm with the user before deleting.
- Remove the policy file from .fragments/policies/.
- Remove its reference from fragments.config.ts if individually listed (not needed if using a glob pattern).
- Confirm deletion.
Common mistakes
CRITICAL: Policy exists but never runs
Forgetting to add the policies glob in fragments.config.ts. The file sits on disk but the governance engine never loads it.
Wrong -- no policies field:
import { defineConfig } from '@fragments-sdk/govern';
export default defineConfig({
cloud: true,
checks: ['accessibility', 'consistency'],
input: './src/**/*.{tsx,jsx}',
});
Correct -- policies glob included:
import { defineConfig } from '@fragments-sdk/govern';
export default defineConfig({
cloud: true,
checks: ['accessibility', 'consistency'],
policies: ['./.fragments/policies/*.ts'],
input: './src/**/*.{tsx,jsx}',
});
HIGH: Multi-concern policy
Bundling unrelated checks into one policy makes it impossible to disable a single rule without losing the others.
Wrong -- one policy checking touch targets, colors, and headings:
export default definePolicy({
name: 'ui-standards',
severity: 'error',
check({ node, report }) {
if (node.type === 'button' && parseFloat(node.computedStyles?.height) < 44) {
report({ message: 'Button too small' });
}
if (node.styles?.color && /^#/.test(node.styles.color)) {
report({ message: 'Hardcoded color' });
}
},
});
Correct -- split into min-button-height.ts and no-hardcoded-colors.ts with one concern each.
MEDIUM: error severity for style preferences
error severity fails CI pipelines. Reserve it for accessibility and functional issues. Use warning for stylistic guidance.
Wrong:
export default definePolicy({
name: 'prefer-semibold',
description: 'Headings should use semibold weight',
severity: 'error',
// ...
});
Correct:
export default definePolicy({
name: 'prefer-semibold',
description: 'Headings should use semibold weight',
severity: 'warning',
// ...
});
Guidelines
- Default severity to warning unless explicitly requested as error
- Always include a human-readable description
- Include an auto-fix in the fix field when possible
- Use kebab-case for policy file names
- One concern per policy -- keep logic focused