@W-22252932 [Meta Skill] Skill Creator (#232)

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator

* @W-22252932 [Meta Skill] Skill Creator
This commit is contained in:
Ayush Gupta 2026-05-04 11:34:12 +05:30 committed by GitHub
parent 8f70982668
commit f5e63fd06a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 1219 additions and 0 deletions

View File

@ -0,0 +1,367 @@
---
name: creating-sf-skill
description: "AI-assisted skill authoring pipeline for the afv-library. Use when the user wants to create a new skill, update an existing skill, generate a skill spec, scaffold skill files, or add a new capability to the skill catalog. TRIGGER when: user says create skill, new skill, skill creator, author skill, scaffold skill, generate skill, update skill, add a skill, skill pipeline. DO NOT TRIGGER when: user is directly editing an existing SKILL.md without asking for guided authoring.Invoke this skill whenever someone needs to add a new capability to the afv-library skill catalog, or wants to update/improve an existing skill. This includes creating skills for Apex, metadata, LWC, Flow, Agentforce, or any Salesforce domain."
license: LICENSE.txt has complete terms
metadata:
version: "1.0"
stage: Pilot
---
# Instructions
You are a contributor onboarding tool for the [afv-library](https://github.com/forcedotcom/afv-library).
Your job is to take minimal input and generate a complete, validated skill as fast as possible.
Ask **one thing at a time**. Generate first, refine after. Do not explain the pipeline.
The full contribution lifecycle has 5 phases:
| Phase | What | Status |
|-------|------|--------|
| 1 | Gather authoritative input | **This skill handles** |
| 2 | Generate v1 Draft | **This skill handles** |
| 3 | Generate test stubs | **This skill handles** |
| 4 | Run eval, move to Under Review | Next step for contributor |
| 5 | Push PR to afv-library, CI publishes | Final step for contributor |
---
## On Start
If the user passed `$ARGUMENTS` (a skill name), check if `skills/$0/SKILL.md` already exists.
If yes, use `AskUserQuestion`: options `Update existing skill` | `Create new skill with different name`.
Otherwise proceed to Step 1.
---
## Step 1 — Infer or confirm skill type
**Try to infer the skill type from the user's message before asking.**
| If the user mentions… | Infer type |
|----------------------|------------|
| metadata, object, field, validation rule, permission set, flow, layout, component, prompt template | Metadata generation |
| Apex class, trigger, batch, LWC, JavaScript, test class | Code generation |
| deploy, debug, setup, migrate, process, pipeline | Workflow / process |
- If confident: state the inferred type inline. Suggest 2-3 gerund skill names, **pick one as your recommendation, and briefly explain why** (e.g. most specific, matches naming convention, clearest intent). Move to Step 2.
- If genuinely uncertain: use `AskUserQuestion`:
```
question: "What kind of skill do you want to create?"
header: "Skill type"
options:
- label: "Metadata generation"
description: "Creates Salesforce metadata — custom objects, fields, validation rules, etc."
- label: "Code generation"
description: "Generates Apex classes, triggers, LWC components, or other code artifacts."
- label: "Workflow / process"
description: "Guides the user through a multi-step process — deployments, debugging, org setup, etc."
- label: "Other"
description: "Something else — I'll describe it."
```
After confirming type, **suggest 2-3 skill names inline** using the gerund naming convention
(e.g., `generating-validation-rule`, `building-data-cloud-connector`). Present as text, not a question.
---
## Step 2 — Describe the skill + gather reference material
**Do not expose step numbers to the user.** Never say "Step 2" or label sections in user-facing messages.
Use `AskUserQuestion` to understand the use case:
```
header: "Use case"
question: "What's the use case for this skill? Tell me what problem it solves, who would use it, and what it should produce.
If you have any examples, schemas, or docs handy, feel free to share them too — a file path, URL, or paste works."
options:
- label: "I'll describe it here"
description: "Type your use case and I'll generate from that."
- label: "I have reference material"
description: "I'll share a schema, example file, or doc."
```
Read every resource the user provides. Then summarize what you extracted — keep it tight, 2-3 bullets max:
> **Extracted context:**
> • …
> • …
**Now generate the description** using both the user's description and the extracted context.
Expand it to include trigger phrases, `TRIGGER when` / `DO NOT TRIGGER when` clauses, and the word "use".
**Print the description as plain text in your response message first**, then call `AskUserQuestion`. The user cannot see the description inside the tool's question or option fields — it must appear in the message body before the tool call.
Example message format:
```
Here's the skill description I've drafted:
> **Skill name:** `generating-<name>`
>
> **Description:** <full description text here>
Does this capture it?
```
Then use `AskUserQuestion`:
```
question: "Does this description capture what you want the skill to do?"
header: "Description"
options:
- label: "Looks good (Recommended)"
description: "Use this and proceed to generation."
- label: "I want to edit it"
description: "Tell me what to change."
```
If they edit, incorporate and re-confirm.
**Silent background work before generating:**
- Scan `skills/` for existing skills with overlapping scope (duplicate check).
- Identify dependency candidates from existing skill names.
- Infer gotchas from domain knowledge and the provided reference material.
---
## Step 3 — Generate
Tell the user: **"Generating Skill..."**
Then do the work. Do not ask any more questions.
1. Read `./references/progressive_disclosure.md` — use it to decide what
goes in SKILL.md vs `assets/` vs `references/` vs `examples/`.
2. Read `./templates/skill_template.md`.
3. Read `./templates/frontmatter_reference.yaml`.
4. Read `./references/best_practices.md`.
5. Generate all files following the rules below.
### What goes WHERE — hard rules
SKILL.md is **only** for the workflow, rules, and gotchas. Everything else goes into subdirectories.
| Content type | Where it goes |
|-------------|---------------|
| Code templates (`.cls`, `.xml`, `.js`, `.html`) | `assets/` |
| Code examples / sample output | `examples/` |
| API specs, schemas, XML definitions | `references/` or `assets/` |
| Detailed reference tables (> 20 rows) | `references/` |
| Step-by-step guides for sub-procedures | `references/` |
| Input/output example pairs | `examples/` |
| Configuration files, manifests | `assets/` |
**What stays in SKILL.md**: frontmatter, overview (1-3 sentences), scope, required inputs,
workflow steps, constraint table, gotchas table (short), output expectations (file list only),
cross-skill integration table, and Reference File Index.
### How to reference files from SKILL.md
Every file in `assets/`, `references/`, or `examples/` **must** have a specific load instruction
in SKILL.md. Use this pattern:
```markdown
1. **Read the service template** — load `assets/service.cls` before generating.
2. **For REST endpoints**, read `references/rest_api_patterns.md` for status codes.
3. **See example output** in `examples/basic_service.cls` for the expected structure.
```
Never write "see references/ for details." Always name the specific file and scenario.
### Directory structure to create
```
skills/<skill-name>/
├── SKILL.md # Workflow + rules + gotchas ONLY (target < 300 lines)
├── assets/ # Code templates, XML schemas, config files
├── references/ # Prose docs, detailed tables, sub-guides
├── examples/ # Input/output pairs, sample generated files
└── tests/
└── evals/
├── <skill-name>-<scenario-1>/
│ ├── prompt.md # Exact trigger prompt (no heading — just the prompt text)
│ └── gold/ # Expected output artifact
├── <skill-name>-<scenario-2>/
│ ├── prompt.md
│ └── gold/
└── <skill-name>-<scenario-3>/
├── prompt.md
└── gold/
```
Read `./templates/tests_structure.md` before scaffolding `tests/`.
Create `assets/`, `references/`, and `examples/` only if there is content to put in them.
Do NOT create `tests/unit/` — only create `tests/evals/` with 2-3 datasets.
### Generating SKILL.md content
**Frontmatter — always set `stage: Draft`:**
```yaml
---
name: <skill-name>
description: "<from Step 2>"
license: LICENSE.txt has complete terms
metadata:
version: "1.0"
stage: Draft
---
```
**Body rules:**
- Add what the agent lacks, omit what it knows.
- Task-oriented: every section = an instruction, not a description.
- Target < 300 lines for SKILL.md body.
**Required sections:**
| Section | What to write |
|---------|---------------|
| Title + overview | 1-3 sentences — what and why |
| Scope | In-scope / out-of-scope boundary |
| Required Inputs | What context to gather before acting |
| Workflow | Numbered steps with `read` instructions |
| Rules | Hard constraints table |
| Gotchas | Short table of pitfalls — max 10 rows |
| Output Expectations | List of files produced (not their content) |
| Cross-Skill Integration | When to delegate (if applicable) |
| Reference File Index | Maps every subdirectory file to when it's read |
### Write all files
1. Write `skills/<skill-name>/SKILL.md`.
2. Write each `assets/` file — code templates, schemas.
3. Write each `references/` file — detailed guides, tables.
4. Write each `examples/` file — sample inputs/outputs.
5. Write `tests/evals/` datasets — see Step 4 below for eval content rules.
### Validate
Run the validator:
```bash
npx tsx scripts/validate-skills.ts 2>&1
```
For the full list of rules, see `./references/validation_rules.md`.
**If validation fails**: fix the issues and re-run. Only surface to the user if you cannot
resolve an issue yourself.
---
## Step 4 — Review
Tell the user:
> **"Your skill is generated and in draft state — please review and let me know if you'd like any changes."**
Then print the file tree and key decisions:
```
skills/<name>/
├── SKILL.md
├── assets/<files>
├── references/<files>
├── examples/<files>
└── tests/
└── evals/<dataset-1>/, <dataset-2>/, <dataset-3>/
Key decisions:
<e.g. "Formula reference table moved to references/ 25 rows, too large for SKILL.md">
<e.g. "assets/template.xml built from the schema provided in context">
<e.g. "5 gotchas inferred from domain knowledge">
```
Use `AskUserQuestion`:
```
question: "Would you like to make any changes?"
header: "Review"
options:
- label: "Looks good"
description: "Proceed to generating eval datasets."
- label: "I want changes"
description: "Tell me what to modify and I'll update the skill."
```
If changes requested: collect feedback, edit files, re-validate, re-print, return here.
---
## Step 5 — Generate eval datasets
Read `./templates/tests_structure.md` before writing eval files.
For each of 2-3 positive trigger scenarios (derived from the skill description):
**`tests/evals/<skill-name>-<scenario>/prompt.md`** — write the exact prompt a user would type.
No heading, no title, no markdown framing — just the raw prompt text:
```
<The exact user message that should trigger this skill>
```
**`tests/evals/<skill-name>-<scenario>/gold/<artifact>`** — expected output file with the
correct extension for the artifact type (e.g. `ContactEmail.validationRule-meta.xml`, `AccountService.cls`).
Infer extension from skill type. Mark with a stub comment at the top:
```
# STUB — review and update expected output before running eval
```
Do **not** create `seed-data/` folders — those are filled in by the contributor during eval.
Use `AskUserQuestion`:
```
question: "Eval stubs generated. How do they look?"
header: "Evals"
options:
- label: "Looks good"
description: "Proceed to next steps."
- label: "Add or change some"
description: "Tell me what to adjust."
```
---
## Step 6 — Done
Print the final summary:
```
Skill: <name>
Location: skills/<name>/
Stage: Draft
What this skill does:
<1-line summary of primary capability>
<key scope boundary or constraint>
<notable pattern, delegation, or integration>
Next steps:
1. Run the eval prompts in tests/evals/ and review the outputs against gold/.
When the outputs look right, update the frontmatter: stage: Under Review
2. Once you're happy with the skill, open a PR to forcedotcom/afv-library.
CI will validate the skill and publish it to the catalog.
```
---
## Gotchas (for you, the agent)
| Issue | What to do |
|-------|------------|
| Description missing "use" | Validator requires it. Always include "Use when..." in generated descriptions. |
| YAML parse error | Descriptions contain `: ` — always wrap in double quotes. |
| Gerund naming | First word must end in `-ing`. Suggest names that follow this. |
| Body over 500 lines | Split into `references/`. See `./references/progressive_disclosure.md`. |
| User gives vague input | Don't ask repeatedly — make your best guess, generate, and confirm. |
| Validation fails | Fix it yourself. Only ask the user if you genuinely can't resolve it. |
| No reference material provided | Generate representative stubs; mark everything `# STUB`. |
| Skill type is clear from user message | Do not ask — infer it, state it, move on. |

View File

@ -0,0 +1,87 @@
---
name: generating-validation-rule
description: "Create and update Salesforce validation rules for any standard or custom object. Use when the user asks to add a validation rule, enforce field requirements, prevent invalid data entry, or implement record-level business logic constraints. TRIGGER when: user says validation rule, field validation, required field check, data constraint, record validation, prevent invalid data. DO NOT TRIGGER when: user asks about Flow validation or Apex validation logic — delegate to generating-flow or generating-apex."
metadata:
version: "1.0"
stage: Draft
license: LICENSE.txt has complete terms
---
# Generating Validation Rules
Create validation rules that enforce business logic at the record level.
## Scope
- **In scope**: Creating new validation rules, updating existing rules, formula syntax,
error message placement, activation/deactivation.
- **Out of scope**: Flow-based validation (use `generating-flow`), Apex triggers for
complex validation (use `generating-apex`).
## Required Inputs
- Target object (standard or custom)
- Business rule to enforce (in plain language)
- Error message text
- Error location (top of page or specific field)
Defaults:
- Active: true
- Description: auto-generated from the business rule
## Workflow
1. **Identify the object** — confirm the API name of the target object.
2. **Understand the rule** — translate the business requirement into a boolean formula.
3. **Check existing rules** — look for overlapping validation rules on the same object.
4. **Read the metadata template** — load `./assets/validation_rule_template.xml` before generating.
5. **Write the formula** — the formula must evaluate to `TRUE` when the data is **invalid**.
For common formula patterns, read `./references/formula_patterns.md`.
6. **Set error message** — clear, user-friendly message explaining what's wrong and how to fix it.
7. **Create metadata file** — generate the `.validationRule-meta.xml` using the template structure.
Compare against `./examples/require_email_on_contact.xml` for expected output format.
8. **Syntax check** — verify the formula compiles (field API names, function syntax).
9. **Edge case review** — test with null values, blank strings, boundary conditions.
## Rules
| Constraint | Rationale |
|-----------|-----------|
| Formula evaluates to TRUE on invalid data | Salesforce convention — TRUE = error |
| Use API names, not labels | Labels change; API names are stable |
| Handle null fields with `ISBLANK()` | Prevent null pointer errors |
| Use `PRIORVALUE()` only in update context | Not available on insert |
## Gotchas
| Issue | Resolution |
|-------|------------|
| Rule fires on record types it shouldn't | Add `RecordType.DeveloperName` check to formula |
| Rule blocks data migration/bulk loads | Add bypass via Custom Permission or Custom Metadata |
| `ISCHANGED()` always false on insert | Guard with `NOT(ISNEW())` before using `ISCHANGED()` |
| Formula too long (> 5000 chars) | Split into multiple rules or use a helper formula field |
| Error on wrong field | Verify field API name in `errorConditionFormula` attribute |
## Output Expectations
Deliverables per validation rule:
- `<ObjectName>.validationRule-meta.xml`
File structure follows the template in `./assets/validation_rule_template.xml`.
## Cross-Skill Integration
| Need | Delegate to |
|------|-------------|
| Complex multi-object validation | `generating-apex` (trigger-based) |
| Flow-based validation with user prompts | `generating-flow` |
| Custom object creation | `generating-custom-object` |
| Field creation for formula references | `generating-custom-field` |
## Reference File Index
| File | When to read |
|------|-------------|
| `./assets/validation_rule_template.xml` | Before generating any validation rule metadata file |
| `./references/formula_patterns.md` | When writing the formula — common patterns and functions |
| `./examples/require_email_on_contact.xml` | To verify generated output matches expected format |

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<ValidationRule xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>{ObjectApiName}.{RuleDeveloperName}</fullName>
<active>true</active>
<description>{Plain language description of what this rule enforces}</description>
<errorConditionFormula>{Formula that evaluates TRUE when data is INVALID}</errorConditionFormula>
<errorDisplayField>{FieldApiName — omit for page-level errors}</errorDisplayField>
<errorMessage>{User-friendly message: what's wrong and how to fix it}</errorMessage>
</ValidationRule>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<ValidationRule xmlns="http://soap.sforce.com/2006/04/metadata">
<fullName>Contact.Require_Email</fullName>
<active>true</active>
<description>Requires an email address on all Contact records</description>
<errorConditionFormula>ISBLANK(Email)</errorConditionFormula>
<errorDisplayField>Email</errorDisplayField>
<errorMessage>Email is required on Contact records. Please provide a valid email address.</errorMessage>
</ValidationRule>

View File

@ -0,0 +1,85 @@
# Common Validation Rule Formula Patterns
## Required field (non-blank)
```
ISBLANK(Field__c)
```
Error: "Field is required."
## Required field only on specific record type
```
AND(
RecordType.DeveloperName = "Enterprise",
ISBLANK(Field__c)
)
```
## Numeric range check
```
OR(
Amount__c <= 0,
Amount__c > 1000000
)
```
Error: "Amount must be between 1 and 1,000,000."
## Date must be in the future
```
Close_Date__c <= TODAY()
```
Error: "Close date must be after today."
## Date comparison (end after start)
```
End_Date__c <= Start_Date__c
```
Error: "End date must be after start date."
## Field changed validation (update only)
```
AND(
NOT(ISNEW()),
ISCHANGED(Stage__c),
ISPICKVAL(PRIORVALUE(Stage__c), "Closed Won")
)
```
Error: "Cannot change stage after Closed Won."
## Bypass with Custom Permission
Wrap any formula to allow admin bypass:
```
AND(
NOT($Permission.Bypass_Validation_Rules),
{your formula here}
)
```
## Regex pattern match (email format)
```
NOT(REGEX(Email__c, "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"))
```
## Cross-field dependency
```
AND(
ISPICKVAL(Type__c, "Partner"),
ISBLANK(Partner_Account__c)
)
```
Error: "Partner Account is required when Type is Partner."

View File

@ -0,0 +1,149 @@
# Skill Authoring Best Practices
Principles for writing high-quality skills. Based on patterns observed across the
afv-library and the Agent Skills best practices guide.
## Core Principles
### 1. Add What the Agent Lacks, Omit What It Knows
The most common mistake is including general knowledge the LLM already has.
Focus exclusively on:
- **Project-specific conventions** — naming patterns, directory structure, coding standards
unique to this project.
- **Domain-specific procedures** — workflows, API quirks, deployment steps that are
not publicly documented or are team-specific.
- **Gotchas** — failure modes, edge cases, known bugs that the agent would not anticipate.
**Omit**: general programming concepts, language syntax, well-known design patterns.
### 2. Extract from a Hands-On Task
The best skills are written after doing the task manually:
1. Perform the task yourself (or watch someone do it).
2. Note every decision point, tool invocation, and gotcha encountered.
3. Write the skill as the instructions you wish you had before starting.
4. Feed real execution traces back into the skill.
### 3. Refine with Real Execution
> "The first draft of a skill usually needs refinement. Run the skill against real
> tasks, then feed the results — all of them, not just failures — back into the
> creation process."
After generating a skill:
- Run it against 3-5 real prompts.
- Read the full execution trace, not just the final output.
- Identify: false positives, false negatives, wasted tokens, vague instructions.
### 4. Task-Oriented, Not Concept-Oriented
Structure skills around what the agent should **do**, not what **exists**.
**Bad**: "Apex supports various class types including Service, Selector, Domain..."
**Good**: "1. Identify the class type needed. 2. Read the matching template from assets/.
3. Generate the class following the template pattern."
### 5. Concise Over Comprehensive
Every token in a SKILL.md costs compute and risks confusing the agent with
irrelevant instructions. Cut ruthlessly:
- Remove sections the agent never follows.
- Remove examples that duplicate other examples.
- Remove caveats about edge cases that never happen.
## Description Writing
The description is the most important field — it determines when the skill triggers.
### Do
- Front-load the primary use case.
- Include specific keywords users say: "Apex", ".cls", "trigger", "batch job".
- Add `TRIGGER when:` and `DO NOT TRIGGER when:` clauses.
- **Be pushy**: list implicit triggers where the user may not use the domain term directly.
- Keep it factual and specific.
### Don't
- Use vague language: "helps with Salesforce development".
- Include implementation details: "uses the AccountService pattern".
- Make it too narrow: only one exact phrase triggers it.
- Make it too broad: triggers on everything.
### Be Pushy About Triggers
Err on the side of listing more implicit triggers, not fewer. A skill that never fires is useless;
a skill that fires on a near-miss is recoverable. Explicitly call out contexts where the skill
applies **even if the user doesn't name the domain directly**:
> "TRIGGER when: user asks to add a rule, restrict a field, or enforce a policy — even if they
> don't explicitly say 'validation rule' or 'Apex'."
This is especially important for domain keywords the user may not know (e.g., they say "make this
field required" not "add a required validation rule").
### Template
```
<Primary purpose statement>. ALWAYS ACTIVATE when <high-confidence triggers>.
Use this skill for <broader use cases>. TRIGGER when: <specific list include implicit
contexts where the user may not use the exact domain term>.
DO NOT TRIGGER when: <exclusions with delegation targets>.
```
## Workflow Structure
### Phase-Based
For multi-step skills, use numbered phases:
```markdown
### Phase 1 — Discover
1. **Read project conventions** — check for existing patterns.
2. **Identify inputs** — what context is needed.
### Phase 2 — Generate
3. **Read template** — load the matching template.
4. **Author code** — generate following the template.
### Phase 3 — Validate
5. **Run checks** — execute validation tools.
6. **Report** — present results.
```
### Decision Matrices
For complex decisions, use tables instead of nested conditionals:
```markdown
| Scenario | Pattern | Template |
|----------|---------|----------|
| Standard async work | Queueable | assets/queueable.cls |
| Large datasets | Batch Apex | assets/batch.cls |
| Recurring schedule | Schedulable | assets/schedulable.cls |
```
## Anti-Patterns
| Anti-Pattern | Why It's Bad | Fix |
|-------------|-------------|-----|
| Wall of text with no structure | Agent can't find relevant instructions | Use headers, tables, numbered steps |
| Generic advice | Wastes tokens on things the agent knows | Add only project-specific knowledge |
| Deeply nested conditionals | Agent loses track of which branch it's in | Flatten into decision tables |
| Too many optional steps | Agent follows all of them, wasting time | Make steps required or remove them |
| Missing gotchas section | Agent hits known pitfalls | Add gotchas from real execution failures |
| Referencing files that don't exist | Agent hallucinates content | Verify all referenced paths exist |
| Duplicating content from other skills | Wastes tokens and risks staleness | Reference the other skill instead |
## Cross-Skill Integration Patterns
When your skill needs another skill's capability:
1. **Delegate explicitly**: "For Apex tests, delegate to `generating-apex-test` skill."
2. **Define boundaries clearly**: "This skill handles X. For Y, use Z skill."
3. **Don't duplicate**: If another skill covers a topic, reference it, don't copy.

View File

@ -0,0 +1,85 @@
# Progressive Disclosure — What Goes Where
SKILL.md is the workflow controller. It tells the agent what to do and when to read other files.
It does **not** contain the detailed content itself.
## Hard Rules
These are not guidelines. Always follow them.
| Content type | Goes in | Example filename |
|-------------|---------|-----------------|
| Code templates | `assets/` | `service.cls`, `batch.cls`, `rest_resource.cls` |
| XML schemas / metadata templates | `assets/` | `meta_template.xml`, `object_schema.xml` |
| Config samples, manifests | `assets/` | `sfdx-project.json`, `package.xml` |
| API reference docs | `references/` | `api_patterns.md`, `rest_endpoints.md` |
| Detailed decision tables (> 20 rows) | `references/` | `error_codes.md`, `field_mappings.md` |
| Step-by-step sub-procedures | `references/` | `deployment_steps.md`, `migration_guide.md` |
| Edge case handling guides | `references/` | `edge_cases.md`, `null_handling.md` |
| Full input/output examples | `examples/` | `basic_usage.md`, `AccountService.cls` |
| Sample generated files | `examples/` | `example_output.xml`, `sample_trigger.trigger` |
## What Stays in SKILL.md
Only these belong in the main file:
- **Frontmatter** (name, description, metadata)
- **Overview** (1-3 sentences)
- **Scope** (in/out boundary)
- **Required Inputs** (bullet list of what to gather)
- **Workflow** (numbered steps with read instructions to subdirectory files)
- **Rules/Constraints** (short table — max 15 rows)
- **Gotchas** (short table — max 10 rows)
- **Output Expectations** (file list only, not content)
- **Cross-Skill Integration** (delegation table)
- **Reference File Index** (maps every subdirectory file to its trigger)
Target: **< 300 lines** for SKILL.md body.
## How to Reference from SKILL.md
Every file in a subdirectory needs a specific load instruction in the workflow section.
**Good — embedded in a workflow step:**
```markdown
1. **Read the service template** — load `assets/service.cls` before generating.
2. **Check error handling patterns** — if the class needs custom exceptions, read `references/error_handling.md`.
3. **Compare against example** — verify output matches `examples/AccountService.cls`.
```
**Good — in the Reference File Index:**
```markdown
| File | When to read |
|------|-------------|
| `assets/service.cls` | Before generating any service class |
| `references/error_handling.md` | When implementing custom exception handling |
| `examples/AccountService.cls` | To verify generated output matches expected format |
```
**Bad — vague references the agent will ignore:**
```markdown
See the `references/` directory for more details.
Check `assets/` for templates.
```
## Common Mistakes
| Mistake | Why it's wrong | Fix |
|---------|---------------|-----|
| Inlining a 50-line code template in SKILL.md | Bloats the file, wastes tokens on every invocation | Put in `assets/`, add a read instruction |
| Pasting an API spec into the workflow | Spec content is static reference, not workflow | Put in `references/`, read only when needed |
| Adding example output inline | Examples are for validation, not every-run context | Put in `examples/`, reference from output section |
| Creating subdirectory but not referencing it | Agent never reads unreferenced files | Add entry to Reference File Index |
| Using "see references/" without naming a file | Agent doesn't know which file to read | Always name the specific file |
## Token Budget
| Component | Target | Maximum |
|-----------|--------|---------|
| SKILL.md body | < 300 lines | 500 lines |
| Single reference file | < 200 lines | 300 lines |
| Single asset file | No line limit | Keep focused on one template |
| Single example file | < 100 lines | 200 lines |

View File

@ -0,0 +1,129 @@
# Validation Rules Reference
Complete reference for all validation checks enforced by `scripts/validate-skills.ts`.
The validator runs structure checks first (before reading SKILL.md), then content checks.
## Structure Checks
These run on every entry in `skills/` before SKILL.md is read.
A fatal error aborts all content checks for that entry.
### 1. Entry Must Be a Directory
- **Severity**: Error (fatal)
- **Rule**: No loose files in `skills/` — only directories.
- **Fix**: Move the file into a skill directory or remove it.
### 2. Must Contain SKILL.md
- **Severity**: Error (fatal)
- **Rule**: Every skill directory must have a `SKILL.md` file.
- **Fix**: Create `SKILL.md` with proper frontmatter and body.
### 3. Name Must Be Kebab-Case
- **Severity**: Error
- **Pattern**: `^[a-z0-9]+(-[a-z0-9]+)*$`
- **Allowed**: lowercase letters, digits, hyphens
- **Not allowed**: uppercase, underscores, dots, spaces
- **Examples**:
- `generating-apex` (valid)
- `Generating-Apex` (invalid — uppercase)
- `generating_apex` (invalid — underscore)
### 4. Name <= 64 Characters
- **Severity**: Error
- **Rule**: Directory name must not exceed 64 characters.
### 5. Gerund First Word
- **Severity**: Warning (not blocking)
- **Rule**: First word of the skill name should end in `-ing`.
- **Rationale**: Convention for consistency (e.g., `generating-`, `building-`, `deploying-`).
- **Examples**:
- `generating-apex` (pass)
- `agentforce-development` (warning — "agentforce" doesn't end in -ing)
### 6. No Nested Skills
- **Severity**: Error
- **Rule**: No subdirectory of a skill may contain its own `SKILL.md`.
- **Fix**: Flatten nested skills to be siblings under `skills/`.
## Content Checks
These run after SKILL.md is read successfully.
### 7. Valid YAML Frontmatter Block
- **Severity**: Error (fatal)
- **Rule**: SKILL.md must start with `---\n...\n---` YAML frontmatter.
- **Fix**: Add frontmatter between `---` delimiters at the top of the file.
### 8. JSON-Compatible YAML
- **Severity**: Error
- **Rule**: Frontmatter must parse with `js-yaml` JSON_SCHEMA.
- **Common cause**: Unquoted values containing `: ` (colon + space).
- **Fix**: Wrap values in single or double quotes.
```yaml
# BAD
description: Primary skill: generates Apex classes
# GOOD
description: "Primary skill: generates Apex classes"
```
### 9. `name` Matches Directory
- **Severity**: Error
- **Rule**: The `name` field in frontmatter must exactly match the directory name.
- **Fix**: Ensure `name: generating-apex` if the directory is `skills/generating-apex/`.
### 10. `description` Present and Non-Empty
- **Severity**: Error
- **Rule**: Frontmatter must include a `description` field with content.
### 11. Body Non-Empty
- **Severity**: Error
- **Rule**: There must be content after the frontmatter block.
### 12. Description >= 20 Words
- **Severity**: Error
- **Rule**: Description must contain at least 20 words.
- **Rationale**: Short descriptions don't provide enough trigger context.
### 13. Description <= 1024 Characters
- **Severity**: Error
- **Rule**: Description must not exceed 1024 characters.
### 14. Description Contains "use"
- **Severity**: Error
- **Rule**: Description must include the word "use" (case-insensitive).
- **Rationale**: Enforces trigger/activation language.
- **Fix**: Include phrases like "Use when...", "Use this skill for...", "Used to...".
### 15. Body <= 500 Lines
- **Severity**: Warning (not blocking)
- **Rule**: Skill body should be under 500 lines for context efficiency.
- **Fix**: Extract detailed content into `references/` with conditional load instructions.
## Running Validation
```bash
# Validate all skills
npm run validate:skills
# Validate only changed skills (CI mode)
npm run validate:skills -- --changed --base=origin/main
# Validate a specific skill (filter output)
npx tsx scripts/validate-skills.ts 2>&1 | grep -A5 "<skill-name>"
```

View File

@ -0,0 +1,92 @@
# AFV-Library Skill Frontmatter — Complete Field Reference
#
# All skills in skills/<name>/SKILL.md must include YAML frontmatter
# between --- delimiters. This file documents every supported field.
#
# Validation: scripts/validate-skills.ts
# ============================================================
# REQUIRED FIELDS
# ============================================================
name:
type: string
required: true
description: "Unique skill identifier. Must match the directory name exactly."
validation:
pattern: "^[a-z0-9]+(-[a-z0-9]+)*$"
max_length: 64
example: "generating-apex"
description:
type: string
required: true
description: >
What the skill does and when it should activate. This is the primary
signal used for skill routing — it must be rich and specific.
validation:
min_words: 20
max_chars: 1024
must_contain: "use"
tips:
- "Include TRIGGER when and DO NOT TRIGGER when clauses"
- "Front-load the most important use case"
- "Include specific keywords users would say"
- "Must be wrapped in double quotes if it contains ': '"
example: >
"Primary Apex authoring skill for class generation, refactoring, and review.
ALWAYS ACTIVATE when the user mentions Apex, .cls, triggers, or asks to
create/refactor a class. Use this skill for requests involving SObject CRUD,
mapping collections, or code review of existing Apex."
# ============================================================
# OPTIONAL FIELDS
# ============================================================
license:
type: string
required: false
description: "License for the skill. Top-level frontmatter field — NOT nested under metadata."
default: "LICENSE.txt has complete terms"
example: "LICENSE.txt"
metadata:
type: object
required: false
fields:
version:
type: string
description: "Version. New skills use \"1.0\"."
example: "1.0"
stage:
type: enum
values: ["Draft", "Under Review", "Published"]
description: "Current lifecycle stage."
argument-hint:
type: string
description: "CLI usage hint shown in autocomplete."
example: "<class-name> [--type service|selector|batch]"
# ============================================================
# COMMON MISTAKES
# ============================================================
#
# 1. Unquoted description with ": " — causes YAML parse error
# BAD: description: Primary skill: generates Apex
# GOOD: description: "Primary skill: generates Apex"
#
# 2. Name doesn't match directory
# Directory: skills/generating-apex/
# Frontmatter name must be: generating-apex
#
# 3. Description too short
# Must be at least 20 words. Include trigger context.
#
# 4. Missing "use" in description
# Validator checks for the word "use" (case-insensitive)
# Include: "Use when...", "Use this skill for...", etc.
#
# 5. license nested under metadata
# BAD: metadata:
# license: ...
# GOOD: license: Apache-2.0 # top-level field

View File

@ -0,0 +1,109 @@
---
name: <SKILL_NAME>
description: "<DESCRIPTION 20+ words, <= 1024 chars, must contain 'use'. Include TRIGGER when and DO NOT TRIGGER when clauses.>"
license: LICENSE.txt has complete terms
metadata:
version: "1.0"
stage: Draft
---
# <Skill Title>
<1-3 sentence overview: what this skill does and why it exists.>
## Scope
- **In scope**: <what this skill handles>
- **Out of scope**: <what this skill does NOT handle delegate to other skills>
---
## Required Inputs
Gather or infer before proceeding:
- <Input 1>: <description and how to obtain>
- <Input 2>: <description and how to obtain>
- <Input 3>: <description and how to obtain>
Defaults unless specified:
- <Default 1>
- <Default 2>
If the user provides a clear, complete request, generate immediately without unnecessary back-and-forth.
---
## Workflow
All steps are sequential. Do not skip or reorder. If blocked, stop and ask for missing context.
1. **<Step name>**
- <Action to take>
- <Expected outcome>
2. **Read the template** — load `assets/<template-file>` before generating.
3. **<Step name>**
- <Action to take>
- For <specific sub-topic>, read `references/<topic>.md`.
4. **<Step name>**
- <Action to take>
- Compare output against `examples/<example-file>`.
---
## Rules / Constraints
<!-- Short table. If > 15 rows, move extras to references/. -->
| Constraint | Rationale |
|-----------|-----------|
| <Rule 1> | <Why this matters> |
| <Rule 2> | <Why this matters> |
---
## Gotchas
<!-- Short table — max 10 rows. Common pitfalls and fixes. -->
| Issue | Resolution |
|-------|------------|
| <Problem 1> | <How to fix it> |
| <Problem 2> | <How to fix it> |
---
## Output Expectations
Deliverables:
- <File 1>: `<path pattern>`
- <File 2>: `<path pattern>`
File structure follows the template in `assets/<template-file>`.
---
## Cross-Skill Integration
<!-- When to delegate to other skills. Remove section if not applicable. -->
| Need | Delegate to |
|------|-------------|
| <Need 1> | `<other-skill>` skill |
| <Need 2> | `<other-skill>` skill |
---
## Reference File Index
<!-- MANDATORY if any assets/, references/, or examples/ files exist. -->
<!-- Map every subdirectory file to the specific scenario that needs it. -->
| File | When to read |
|------|-------------|
| `assets/<template-file>` | Before generating — use as the starting structure |
| `references/<topic>.md` | When handling <specific scenario> |
| `examples/<example-file>` | To verify generated output matches expected format |

View File

@ -0,0 +1,98 @@
# Tests Directory Structure
Every skill in afv-library must include a `tests/` directory. This is the canonical layout.
## Full Structure
```
skills/<skill-name>/
└── tests/
└── evals/
├── <skill-name>-<scenario-1>/
│ ├── prompt.md # Exact trigger prompt for this scenario
│ ├── gold/ # Expected output artifact(s)
│ └── seed-data/ # Input dependencies
├── <skill-name>-<scenario-2>/
│ ├── prompt.md
│ ├── gold/
│ └── seed-data/
└── <skill-name>-<scenario-3>/
├── prompt.md
├── gold/
└── seed-data/
```
---
## evals/
### Dataset naming
`<skill-name>-<short-scenario>` — kebab-case, descriptive, specific to the test case.
Examples:
- `generating-validation-rule-required-field`
- `generating-apex-service-class`
- `deploying-permission-set-with-field-access`
Generate **2-3 datasets** covering the main positive trigger scenarios. Scenarios should be
distinct — different objects, different rule types, or different complexity levels.
### prompt.md
The exact prompt a user would type to trigger the skill for this scenario. No heading, no title,
no markdown framing — just the raw prompt text.
**Format:**
```
<The exact user message that should trigger this skill>
```
**Example:**
```
Create a validation rule that requires the Email field on the Contact object.
```
### gold/
Expected output artifact(s) the skill should produce. Use the correct file extension for the
artifact type — do not use `expected.md`.
| Skill type | Extension examples |
|------------|-------------------|
| Validation rule | `ContactEmailRequired.validationRule-meta.xml` |
| Apex class | `AccountService.cls` |
| LWC component | `myComponent.html`, `myComponent.js` |
| Custom object | `My_Object__c.object-meta.xml` |
| Permission set | `My_Permission_Set.permissionset-meta.xml` |
Mark the top of every gold file as a stub:
```
<!-- STUB — review and update expected output before running eval -->
```
or for non-XML:
```
# STUB — review and update expected output before running eval
```
### seed-data/
Input dependencies the eval needs to run. This is the context the skill would normally gather
from the org or the user:
- Object field lists (JSON)
- Existing metadata samples (XML)
- Schema fragments
- Any other input fixture
Derive from reference material provided during authoring. If none was provided, generate
representative seed data and mark it as a stub.
---
## Lifecycle
| Stage | Who | Action |
|-------|-----|--------|
| Draft | Agent (this skill) | Scaffold all stubs, mark everything `# STUB` |
| Under Review | Contributor | Fill in gold files, validate fixtures, run evals manually |
| Published | CI | Evals run automatically on PRs |