| name | salesforce-validation-rule-writer-skill |
| description | Converts business rules described in plain English into deployable Salesforce validation rule formula syntax, including error message copy, profile bypass logic, null handling, and formula compilation safety. TRIGGER when: user says write a validation rule, create validation rule formula, block user from saving if, require field when, prevent save when, enforce that field must be filled. Trigger phrases: validation rule for, formula to block, required field logic, save condition. DO NOT TRIGGER when: reviewing existing validation rules for quality (use salesforce-platform-admin-review-agent), deploying validation rules (use salesforce-deployment-validator-skill), bulk updating multiple rules across objects (use salesforce-bulk-data-ops-skill). |
| license | MIT |
| allowed-tools | Read Grep Glob |
| metadata | {"author":"github: Raishin","version":"0.1.0","updated":"2026-05-21","category":"generation","lifecycle":"experimental","execution_tier":"static-review","mcp_servers":[],"oauth_scopes":[],"run_as_permissions":{"required":[],"denied":[]}} |
salesforce-validation-rule-writer-skill
Pure-generation T0 skill that translates plain-English business rules into
production-ready Salesforce validation rule formula syntax. Outputs the
formula, a clear error message, profile bypass guidance, null handling,
and a formula compilation checklist. Nothing is deployed — this skill
generates text only.
When This Skill Owns the Task
Use salesforce-validation-rule-writer-skill when the request is to write
or design a validation rule formula:
- "Write a validation rule that requires Billing Country when the account type is Partner"
- "Block reps from saving an Opportunity with Stage = Closed Won if Amount is blank"
- "Create a formula to enforce that Close Date cannot be in the past on new records"
- "Require phone number when Lead Source is Outbound"
- "Prevent picklist selection of Status = Inactive if there are open Cases"
Delegate elsewhere when:
| Situation | Skill to use |
|---|
| Reviewing or auditing existing validation rule logic | salesforce-platform-admin-review-agent |
| Deploying the generated formula to an org | salesforce-deployment-validator-skill |
| Bulk enabling/disabling many rules across objects | salesforce-bulk-data-ops-skill |
| Need to check what existing rules are on an object | salesforce-metadata-fetcher-skill |
Required Context to Gather First
Before generating a formula, confirm:
- Target object — standard (Account, Contact, Opportunity, Lead, Case)
or custom (
My_Object__c).
- Field API names — the exact API names of every field referenced in the
rule. Ask if only labels are provided.
- Trigger condition — precisely when should the save be blocked? Describe
the AND/OR logic in English.
- Record types in scope — does the rule apply to all record types or only
specific ones? (Affects
RecordType.DeveloperName branching.)
- New vs. edit context — should the rule fire on new records only, edits
only, or both? (
ISNEW, ISCHANGED implications.)
- Profile bypass requirement — which profiles (if any) should be exempt?
(System Admin bypass is almost always required.)
- Error message placement — field-level error or page-level error?
- Picklist field types — if picklist fields are used, confirm the exact
API values (not labels) of the controlling values.
If any critical context is missing, ask before generating.
Recommended Workflow
Step 1 — Confirm and rephrase the business rule
Restate the rule in your own words to confirm understanding:
"This rule fires when: [condition]. It blocks save with: [error text].
It is bypassed for: [profile/record type]. It applies on: [new/edit/both]."
Ask for confirmation before proceeding.
Step 2 — Decompose into atomic conditions
Break the rule into atomic boolean conditions. Map each condition to
the appropriate Salesforce formula function:
| Condition type | Formula pattern |
|---|
| Field is blank | ISBLANK(Field__c) for text; ISNULL(Field__c) for number/date |
| Field equals picklist value | TEXT(Field__c) = "API_Value" |
| Field changed | ISCHANGED(Field__c) |
| New record | ISNEW |
| Prior value comparison | PRIORVALUE(Field__c) |
| Record type check | RecordType.DeveloperName = "RecordTypeName" |
| Date in past | Field__c < TODAY |
Step 3 — Compose the formula with AND/OR/NOT
Wrap atomic conditions using:
AND(cond1, cond2) — both must be true
OR(cond1, cond2) — either must be true
NOT(cond) — negation
Prefer explicit AND/OR over &&/|| operators for readability
and tooling compatibility. Nest carefully — Salesforce formulas have a
5,000-character compiled size limit.
Step 4 — Add profile bypass
Unless the customer explicitly opts out, wrap the core logic with a
System Administrator bypass:
AND(
$Profile.Name <> "System Administrator",
<your_core_formula>
)
For additional profiles, use:
AND(
NOT(OR(
$Profile.Name = "System Administrator",
$Profile.Name = "Sales Ops"
)),
<your_core_formula>
)
Step 5 — Apply null handling
Validate that every text, date, and number field access guards against
null where needed:
- Text fields: use
ISBLANK not = ""
- Number/currency fields: use
ISNULL or BLANKVALUE(Field__c, 0) before
arithmetic
- Date fields: use
ISNULL or compare after null guard
- Picklist fields: use
TEXT(Field__c) = "Value" not Field__c = "Value"
- Multi-select picklists: use
INCLUDES(Field__c, "Value")
Step 6 — Write the error message
Apply these principles (see references/error-message-style.md):
- 15 words or fewer for the primary instruction
- Start with what the user must do, not what they did wrong
- Name the specific field or value required
- Include the condition context when space allows
- No jargon: avoid "null", "API name", "formula"
Good: "Close Date cannot be in the past. Set a future date to save."
Bad: "Validation error: CloseDate field value failed validation formula."
Step 7 — Compile safety check
Before emitting, verify mentally:
Step 8 — Emit structured output
Produce the full output block per the Output Format section below.
Quality Scoring Rubric (100-point)
Score every output before emitting. Threshold: 85+ ship, 70–84 ship with
caveat, below 70 reject and revise.
| Dimension | Points | What earns full marks |
|---|
| Formula correctness | 30 | Formula evaluates to TRUE when it should block; correct operators; picklist TEXT wrapper; ISBLANK/ISNULL appropriately placed |
| Error message clarity | 20 | ≤ 15 words, action-oriented, names the required field or condition, no technical jargon |
| Profile bypass awareness | 15 | System Admin bypass present unless explicitly opted out; additional profiles listed; bypass wrapper syntactically correct |
| Null handling | 15 | Every field access null-guarded; no runtime errors on blank fields; BLANKVALUE used where arithmetic is involved |
| Governor limit safety | 10 | Compiled size < 5,000 chars; no cross-object formula chain deeper than 5 hops; no expensive SOQL-like patterns in formulas |
| Formula compilation safety | 10 | PRIORVALUE/ISCHANGED gated by NOT(ISNEW); no division by zero; no circular references; all functions used with correct argument counts |
Scoring penalties:
- Formula evaluates to FALSE when it should block (inverted logic): -30
- Missing null guard on a field that can be blank in the target object: -10 per field (max -20)
- Missing System Admin bypass when not explicitly opted out: -10
- Error message exceeds 30 words: -10
- PRIORVALUE used without ISNEW guard: -15
T0 Contract
This skill is static-review (T0) only:
- No Salesforce org connection required or permitted.
- No CLI commands are executed.
- No metadata is fetched from a live org.
- Output is a text formula and supporting notes only.
- The user must copy the formula into Setup → Object Manager → Validation Rules
or deploy it via
salesforce-deployment-validator-skill.
Refusal Triggers
Stop and decline if:
- The request is to review or audit an existing formula (route to
salesforce-platform-admin-review-agent).
- The request is to deploy the formula to a live org (route to
salesforce-deployment-validator-skill).
- The formula requested would bypass all validation for all profiles
permanently (security risk — flag and decline).
- The target object cannot be determined after two clarification attempts.
Output Format
verdict: "ship | ship-with-caveat | reject"
quality_score: <0-100>
quality_notes: "<what drove the score>"
validation_rule:
object_api_name: "<SObjectApiName>"
rule_name_suggestion: "<DescriptiveRuleName_NoSpaces>"
active: true
description: "<one-sentence plain English description>"
error_condition_formula: |
<multiline formula text>
error_message: "<≤15 word actionable message>"
error_display_field: "<FieldApiName | blank for page-level>"
profile_bypass:
included: <true|false>
profiles_bypassed: ["System Administrator"]
notes: "<any bypass caveats>"
null_handling_notes: "<summary of null guards applied>"
compilation_checklist:
formula_is_true_when_blocking: <true|false>
priorvalue_gated_by_isnew: <true|false|not_applicable>
ischanged_gated_by_isnew: <true|false|not_applicable>
no_division_by_zero: <true|false>
all_picklists_use_text_wrapper: <true|false|not_applicable>
compiled_size_estimate: "<characters>"
deployment_notes: "<instructions for deploying in Setup UI or via Change Set>"
handoff_suggestions:
Redaction Rules
This is a T0 generation skill with no live org connection. Apply:
- Never emit actual production org IDs, user IDs, or credentials even if
the user includes them in their prompt.
- Sanitize any pasted metadata that includes Org IDs (18-char starting
00D)
or User IDs (18-char starting 005) before incorporating into output.
- Do not include field values that appear to be real customer data (e.g.,
email addresses, account names, SSNs) in example output.
Handoff Rules
| Situation | Hand off to |
|---|
| User wants to deploy the generated rule | salesforce-deployment-validator-skill |
| User wants to review existing rules on the object | salesforce-metadata-fetcher-skill → salesforce-platform-admin-review-agent |
| Formula involves complex record types or permission topology | salesforce-permission-model-review-skill |
| User needs bulk enable/disable of rules | salesforce-bulk-data-ops-skill |
Stop Conditions
- Requested formula would unconditionally block all saves on a standard
critical object (Account, Contact, Opportunity) without any bypass — stop
and require explicit confirmation plus bypass design.
- Formula references fields that do not exist on the stated object — stop,
list the missing fields, ask for correct API names.
- Rule logic contradicts itself (e.g., require field X when X is already
required by a page layout rule that cannot be changed) — stop and
surface the conflict.
Security Notes
- T0 static generation only: No org connection, no CLI, no MCP calls.
- No credential handling: Skill never requests or emits OAuth tokens,
session IDs, or Connected App credentials.
- Profile bypass required by default: Unconditional validation rules
without System Admin bypass are a common data-migration blocker and
governance risk — always include unless explicitly opted out with
documented reason.
- Formula compilation safety: Inverted formula logic (evaluates FALSE
when it should block) is the most common validation rule bug. The
compilation checklist catches this before emission.
Reference File Index
| File | When to read |
|---|
references/formula-syntax-quickref.md | Operators, ISBLANK/ISNULL, AND/OR/NOT, TEXT/VALUE/DATEVALUE, BLANKVALUE, PRIORVALUE |
references/validation-patterns.md | Required-when patterns, prevent-bypass-by-profile, conditional require by record type, dependent picklist validation |
references/error-message-style.md | Concise actionable errors, no jargon, point to fix |