skills/claude-skills-open/skills/crm/change-review/SKILL.md
Validate CRM/PM changes before PR
npx skillsauth add aaaaqwq/agi-super-team change-reviewInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Review of CRM and PM data changes before PR -- a data equivalent of code-review
Public repository: https://github.com/your-org/claude-change-review-skill
| What | Path |
|------|------|
| CRM | $CRM_PATH/ |
| CRM Schema | $CRM_PATH/schema.yaml |
| PM | $PM_PATH/ |
# ALWAYS read the schema first -- it contains all the rules
cat $CRM_PATH/schema.yaml
Schema contains:
primary_key -- unique identifierrequired -- required fieldsunique -- unique fieldsforeign_keys -- relationships between tablescomposite_unique -- composite unique keysenums -- allowed valuesid_format -- regex for ID formatrules -- business rulesgit diff HEAD -- sales/crm/
import pandas as pd
import yaml
# Read schema
with open('$CRM_PATH/schema.yaml') as f:
schema = yaml.safe_load(f)
# Load all tables
base_path = '$CRM_PATH/'
tables = {}
for table_name, table_def in schema['tables'].items():
tables[table_name] = pd.read_csv(base_path + table_def['file'])
import re
def validate_table(name, df, table_schema, all_tables):
issues = []
# 1. Primary key uniqueness
pk = table_schema['primary_key']
if df[pk].duplicated().any():
dups = df[df[pk].duplicated()][pk].tolist()
issues.append(('critical', f'Duplicate {pk}: {dups}'))
# 2. Required fields
for field in table_schema.get('required', []):
missing = df[df[field].isna()]
if len(missing) > 0:
issues.append(('critical', f'Missing required {field}: {len(missing)} rows'))
# 3. Unique fields
for field in table_schema.get('unique', []):
if field == pk:
continue
dups = df[df[field].notna() & df[field].duplicated()]
if len(dups) > 0:
issues.append(('high', f'Duplicate {field}: {dups[field].tolist()}'))
# 4. Foreign keys
for fk_field, ref in table_schema.get('foreign_keys', {}).items():
ref_table, ref_field = ref.split('.')
valid_values = all_tables[ref_table][ref_field]
invalid = df[df[fk_field].notna() & ~df[fk_field].isin(valid_values)]
if len(invalid) > 0:
issues.append(('critical', f'Invalid {fk_field} references: {invalid[fk_field].tolist()}'))
# 5. Composite unique
for fields in table_schema.get('composite_unique', []):
dups = df[df.duplicated(subset=fields, keep=False)]
if len(dups) > 0:
issues.append(('critical', f'Duplicate {"+".join(fields)} combination'))
# 6. Enum values
for field, valid_values in table_schema.get('enums', {}).items():
invalid = df[df[field].notna() & ~df[field].isin(valid_values)]
if len(invalid) > 0:
issues.append(('high', f'Invalid {field} values: {invalid[field].unique().tolist()}'))
# 7. ID format
if 'id_format' in table_schema:
pattern = table_schema['id_format']
invalid = df[~df[pk].str.match(pattern, na=False)]
if len(invalid) > 0:
issues.append(('low', f'Invalid ID format: {invalid[pk].tolist()}'))
return issues
# Validate all tables
for name, table_schema in schema['tables'].items():
if name in tables:
issues = validate_table(name, tables[name], table_schema, tables)
for severity, msg in issues:
print(f'[{severity.upper()}] {name}: {msg}')
# Example: won_lead_has_client
if 'leads' in tables and 'clients' in tables:
won_leads = tables['leads'][tables['leads']['stage'] == 'won']
for _, lead in won_leads.iterrows():
client_exists = (
(tables['clients']['company_id'] == lead['company_id']) &
(tables['clients']['product_id'] == lead['product_id'])
).any()
if not client_exists:
print(f"[HIGH] Won lead without client: {lead['lead_id']}")
## Change Review Summary
**Schema version:** 1.0
**Files reviewed:** [list]
**Risk Level:** Critical / High / Medium / Low
### Critical Issues (must fix)
- [table:field] Description
### High Priority
- [table:field] Description
### Validation by Schema
- [x] Primary keys unique
- [x] Required fields present
- [x] Foreign keys valid
- [x] Enum values valid
- [x] Business rules passed
| Level | Schema Rule | Examples | |-------|-------------|----------| | Critical | primary_key, required, foreign_keys, composite_unique | Duplicate ID, broken FK | | High | unique, enums, rules | Duplicate email, invalid status | | Medium | (manual check) | Missing optional fields | | Low | id_format | Wrong ID pattern |
| Problem | Solution | |---------|----------| | Broken FK | Add parent record or fix ID | | Duplicate PK | Change ID or remove duplicate | | Invalid enum | Use values from schema.yaml | | Wrong ID format | See id_format in schema.yaml |
add-lead -- adding records (also reads schema.yaml)update-lead -- updating recordscode-review -- for code (not data)development
Technology-agnostic prompt generator that creates customizable AI prompts for scanning codebases and identifying high-quality code exemplars. Supports multiple programming languages (.NET, Java, JavaScript, TypeScript, React, Angular, Python) with configurable analysis depth, categorization methods, and documentation formats to establish coding standards and maintain consistency across development teams.
tools
Expert-level browser automation, debugging, and performance analysis using Chrome DevTools MCP. Use for interacting with web pages, capturing screenshots, analyzing network traffic, and profiling performance.
data-ai
Prompt for creating detailed feature implementation plans, following Epoch monorepo structure.
tools
Interactive prompt refinement workflow: interrogates scope, deliverables, constraints; copies final markdown to clipboard; never writes code. Requires the Joyride extension.