mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-08-01 04:16:17 +08:00
@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:
parent
8f70982668
commit
f5e63fd06a
367
skills/creating-sf-skill/SKILL.md
Normal file
367
skills/creating-sf-skill/SKILL.md
Normal 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. |
|
||||
@ -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 |
|
||||
@ -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>
|
||||
@ -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>
|
||||
@ -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."
|
||||
149
skills/creating-sf-skill/references/best_practices.md
Normal file
149
skills/creating-sf-skill/references/best_practices.md
Normal 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.
|
||||
@ -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 |
|
||||
129
skills/creating-sf-skill/references/validation_rules.md
Normal file
129
skills/creating-sf-skill/references/validation_rules.md
Normal 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>"
|
||||
```
|
||||
@ -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
|
||||
109
skills/creating-sf-skill/templates/skill_template.md
Normal file
109
skills/creating-sf-skill/templates/skill_template.md
Normal 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 |
|
||||
98
skills/creating-sf-skill/templates/tests_structure.md
Normal file
98
skills/creating-sf-skill/templates/tests_structure.md
Normal 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 |
|
||||
Loading…
Reference in New Issue
Block a user