Back to list
zotoio

xfi-create-rule

by zotoio

cli for opinionated framework adherence checks

1🍴 0📅 Jan 18, 2026

SKILL.md


name: xfi-create-rule description: End-to-end guide for creating a new X-Fidelity analysis rule. Use when creating rules, adding new checks, or when the user asks about rule development.

Creating X-Fidelity Rules

This skill guides you through creating new analysis rules for X-Fidelity.

Rule Types

TypeSuffixWhen It RunsExample Use Case
Global-globalOnce per repositoryMissing required files, dependency checks
Iterative-iterativeOnce per matching fileCode complexity, pattern detection

Quick Start Checklist

Copy this checklist to track progress:

Rule Creation Progress:
- [ ] Step 1: Define rule purpose and type
- [ ] Step 2: Find or create required fact
- [ ] Step 3: Find or create required operator
- [ ] Step 4: Write rule JSON
- [ ] Step 5: Add to archetype
- [ ] Step 6: Test the rule

Step 1: Define Rule Purpose

Determine:

  1. What the rule checks: Specific condition to detect
  2. Rule type: Global (repo-wide) or iterative (per-file)
  3. Event type: warning (informational) or fatality (blocks CI)

Step 2: Find or Create Required Fact

Facts collect data. Check existing facts in packages/x-fidelity-plugins/src/.

Existing Facts by Plugin

PluginFacts
xfiPluginAstfunctionComplexity, functionCount, astFact
xfiPluginDependencyrepoDependencyFacts
xfiPluginFilesystemrepoFilesystemFacts
xfiPluginPatternsglobalFileAnalysis
xfiPluginReactPatternseffectCleanup, hookDependency
xfiPluginRequiredFilesmissingRequiredFiles
xfiPluginExtractValuesextractValues
xfiPluginSimpleExamplecustomFact

Creating a New Fact

If no existing fact works, create one in the appropriate plugin:

File: packages/x-fidelity-plugins/src/xfiPlugin{Name}/facts/{factName}Fact.ts

import { FactDefn } from '@x-fidelity/types';
import { pluginLogger } from '@x-fidelity/core';

interface MyFactParams {
    resultFact?: string;
    threshold?: number;
}

export const myFact: FactDefn = {
    name: 'myFact',
    description: 'Description of what this fact collects',
    type: 'iterative-function',  // or 'global-function'
    priority: 1,
    fn: async (params: unknown, almanac?: unknown): Promise<any> => {
        const logger = pluginLogger.createOperationLogger('plugin-name', 'myFact');
        const factParams = params as MyFactParams;
        
        // Collect and return data
        const result = { /* collected data */ };
        
        // Optionally store result for later reference
        if (factParams?.resultFact && almanac?.addRuntimeFact) {
            almanac.addRuntimeFact(factParams.resultFact, result);
        }
        
        return result;
    }
};

Add to plugin index: Export the fact in packages/x-fidelity-plugins/src/xfiPlugin{Name}/index.ts

Step 3: Find or Create Required Operator

Operators compare values. Check existing operators in the same plugin locations.

Common Built-in Operators

From json-rules-engine:

  • equal, notEqual
  • greaterThan, lessThan, greaterThanInclusive, lessThanInclusive
  • in, notIn, contains, doesNotContain

Creating a New Operator

File: packages/x-fidelity-plugins/src/xfiPlugin{Name}/operators/{operatorName}.ts

import { OperatorDefn } from '@x-fidelity/types';
import { pluginLogger } from '@x-fidelity/core';

export const myOperator: OperatorDefn = {
    name: 'myOperator',
    description: 'Description of comparison logic',
    fn: (factValue: any, operatorValue: any): boolean => {
        const logger = pluginLogger.createOperationLogger('plugin-name', 'myOperator');
        
        // Compare factValue against operatorValue
        // Return true if condition is met (rule triggers)
        return factValue > operatorValue;
    }
};

Add to plugin index: Export the operator alongside facts.

Step 4: Write Rule JSON

Create rule file in packages/x-fidelity-democonfig/src/rules/

Iterative Rule Template

File: {ruleName}-iterative-rule.json

{
    "name": "myRule-iterative",
    "conditions": {
        "all": [
            {
                "fact": "fileData",
                "path": "$.fileName",
                "operator": "notEqual",
                "value": "REPO_GLOBAL_CHECK"
            },
            {
                "fact": "myFact",
                "params": {
                    "resultFact": "myRuleResult",
                    "threshold": 10
                },
                "operator": "myOperator",
                "value": true
            }
        ]
    },
    "event": {
        "type": "warning",
        "params": {
            "message": "Description of what was detected",
            "details": {
                "fact": "myRuleResult"
            }
        }
    }
}

Global Rule Template

File: {ruleName}-global-rule.json

{
    "name": "myRule-global",
    "conditions": {
        "all": [
            {
                "fact": "fileData",
                "path": "$.fileName",
                "operator": "equal",
                "value": "REPO_GLOBAL_CHECK"
            },
            {
                "fact": "myFact",
                "params": {
                    "resultFact": "myRuleResult"
                },
                "operator": "myOperator",
                "value": true
            }
        ]
    },
    "event": {
        "type": "fatality",
        "params": {
            "message": "Critical issue detected",
            "details": {
                "fact": "myRuleResult"
            }
        }
    }
}

Key Rule Elements

ElementPurpose
nameRule identifier with -iterative or -global suffix
conditions.allAll conditions must be true
conditions.anyAt least one condition must be true
factName of the fact to evaluate
paramsParameters passed to the fact
params.resultFactStore result for use in event message
operatorComparison operator to use
valueValue to compare against
event.typewarning or fatality
event.params.details.factReference stored result in message

Step 5: Add to Archetype

Edit the archetype configuration to include your rule.

File: packages/x-fidelity-democonfig/src/{archetype-name}.json

{
    "name": "node-fullstack",
    "rules": [
        "existingRule-iterative",
        "myRule-iterative"
    ]
}

Note: Rule name in archetype omits the -rule.json suffix but includes -iterative or -global.

Step 6: Test the Rule

Run tests

# Test the plugin
yarn workspace @x-fidelity/plugins test

# Run full test suite
yarn test

Test with CLI

# Run analysis against test fixtures
cd packages/x-fidelity-fixtures/node-fullstack
yarn xfi --configServer local --archetype node-fullstack --debug

Verify rule behavior

  1. Check that the rule triggers when expected
  2. Verify event message contains correct details
  3. Confirm rule doesn't trigger on false positives

Troubleshooting

Rule Not Triggering

  1. Verify fact is returning expected data
  2. Check operator comparison logic
  3. Confirm rule is added to archetype
  4. Check file matches inclusion patterns

Rule Triggering Incorrectly

  1. Review fact data collection
  2. Verify operator comparison threshold
  3. Check condition logic (all vs any)

Files Reference

PurposeLocation
Factspackages/x-fidelity-plugins/src/xfiPlugin*/facts/
Operatorspackages/x-fidelity-plugins/src/xfiPlugin*/operators/
Rulespackages/x-fidelity-democonfig/src/rules/
Archetypespackages/x-fidelity-democonfig/src/*.json
Plugin registrypackages/x-fidelity-plugins/src/index.ts

Score

Total Score

60/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

Reviews

💬

Reviews coming soon