Demo deployment rules
Canonical deployment rules for Flows, Apex, LWC, Agentforce, Page Layouts, Queues, and Picklists in SF Demo Prep. Pattern-gated 3-attempt rule, known deploy-error patterns, rollback commands, and per-category deployment procedures. TRIGGER when: a phase sub-agent needs deployment rules outside its inlined scope, or needs to verify rollback command syntax. DO NOT TRIGGER when: deploying metadata (phase prompts inline the relevant rules), during sparring, or for permission set generation.From its SKILL.md
npx -y skills add seb-schi/sf-demo-scout --skill demo-deployment-rulesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
22.1 KB, as published. Nobody here has run it
Deployment Rules — Canonical Reference
One home per category:
- Phase 1 (Queues, Picklists, Page Layouts, Lightning Record Page field sections, Business Processes, Paths) — rules live inlined under IF markers in
${CLAUDE_PLUGIN_ROOT}/prompts/building/phase1.md. This skill file does NOT duplicate them. If a Phase 1 sub-agent needs a rule, it reads its own prompt. - Phase 2 and Phase 3 (Flows, Apex, LWC, Agentforce) — phase prompts delegate to external skills (
sf-flow,platform-apex-generate,experience-lwc-generate,agentforce-generate). This skill file carries the rollback commands, the attempt-rule meta-rule, unfamiliar-error escalation, and Script Deliverable Rules that the phase prompts reference but do not inline. The Known Deploy-Error Patterns catalog lives inreferences/deploy-error-patterns.md(loaded on demand on a deploy failure). - Cross-phase — Script Deliverable Rules (below) apply to any sub-agent producing a reusable shell / language script, regardless of phase.
Attempt rule (max 3, pattern-gated): every retry must carry a new fix — never redeploy unchanged metadata, it fails identically.
- Attempt 1 — deploy. On failure, check the error against the Known Deploy-Error Patterns section below.
- Attempt 2 — if the error matched a pattern, apply the documented fix and redeploy. If no pattern matched, follow the Unfamiliar-errors path, then redeploy.
- Attempt 3 — allowed ONLY if attempt 2 surfaced a different error that also carries a new fix (a different matched pattern, or a docs-consult insight). Apply it and redeploy.
- STOP when an attempt fails with no new fix available, or after attempt 3. Record the item as SKIPPED in your JSON output with the error message and the pattern id(s) tried, and continue with remaining items. Do not wrestle with a broken deploy.
Unfamiliar errors: if the error message is not self-evident, not already
in a loaded orgs/lessons/ topic, and not matched by a Known Deploy-Error Pattern, invoke
the demo-docs-consultation skill before the next attempt. Record the
consultation in docs_consulted.
Known Deploy-Error Patterns
The full catalog of deterministic fixes for recurring Salesforce metadata
deploy errors lives in
references/deploy-error-patterns.md.
On a deploy failure, read that file, match the error, and apply the
documented fix — the attempt rule above counts a match as the next attempt.
These are org-agnostic parse errors (distinct from orgs/lessons/, which
holds org-specific gotchas); a rule-based fix is preferred over improvising.
The catalog currently covers FlexiPage (Pattern A — duplicate
componentInstance; Pattern B — design-time component not found), PermissionSet
(Pattern C — FLS on a required / master-detail field), and LWC (Pattern D —
literal in template expression / apiVersion-66). Pattern B removes a component
the SE must re-add via Lightning App Builder → SE Manual Checklist. To extend
the catalog, add a new pattern there via /project-sparring; org-specific
gotchas still go to orgs/lessons/ (topic-clustered).
Script Deliverable Rules (cross-phase)
Applies whenever a sub-agent produces a reusable shell or language script as part of its deliverable — data-seeding scripts, Apex test-data factories, agent smoke-test harnesses, cleanup scripts. The script is an SE-runnable artifact that outlives the session.
Default execution pattern (Pattern B — idempotent script):
- The script MUST be idempotent — safe to re-run after partial success. Upserts or existence-check-then-insert over blind inserts; external-Id lookups over hardcoded Ids.
- The script MUST expose a
--pilot-onlyflag that exercises every distinct command/object path the bulk run uses — one real guarded write per (CLI verb × target object) combination, against one target record each (or the minimum viable slice) — before the bulk path runs. A pilot that touches only one path while the bulk run uses several is structurally unable to catch a bug in the untested paths. Exit code 0 with expected counts on every exercised path = pass; anything else = fail. - The orchestrator runs the script within the current session after SE confirmation (immediate verified state). The same script is the SE's re-run path for future re-spins or handoffs.
- If the script cannot be idempotent for a legitimate reason (single-shot schema migration, destructive cleanup), Pattern A applies: a resumable sub-agent invoked via SendMessage. Document the reason in
discovery_notes. Pattern B is the default; Pattern A is the exception.
Mandatory self-test before returning the deliverable:
bash -n [script]— syntax check. Cheap insurance against later edits; will NOT catch runtime bugs (subshell exports,declare -Aunder Bash 3.2, JSON envelope unwrap, while-loop counter scope). Run it anyway.bash [script] --pilot-onlyagainst the live target org — the mandatory step that exercises every distinct command/object path at low cost. If the bulk run doesimport bulkon three objects plus anupdate recordon a fourth, the pilot MUST exercise all four (verb × object) combinations, not just the cheapest one — a pilot that validates a single path while the real run uses several will certify a script whose untested paths are broken. Confirm exit 0 AND expected record counts (e.g., 1 pilot record per exercised path) BEFORE returning the sub-agent's output. This is what actually catches the Bash 3.2 / declare -A class of failure AND a wrong CLI verb on a path the pilot would otherwise skip.- If the self-test fails, fix the script and re-run
--pilot-onlyuntil it passes. Every bug caught during self-test goes in theissuesarray verbatim (with the error or symptom). Do NOT hide them behind a successful final run — the orchestrator and the SE need to know what was fragile. The sub-agent MUST be honest about the state of its deliverable. - If a bug reflects a runtime-environment design constraint that future sub-agents should know about (e.g., "target SE Mac runs Bash 3.2 — avoid
declare -A, use temp-file JSON for Python↔bash state handoff"), record it indiscovery_notesas well — it carries forward;issuesis this session only.
SE-runnable standalone contract:
- Same flags, same exit codes, same idempotency whether the orchestrator or the SE runs it.
- No hardcoded session paths, temp-file assumptions, or parent-shell state. The script self-contains everything it needs.
- Script lives at
orgs/[alias]-[customer]/[script-name].sh(or language-appropriate extension). Change log records its path and the--pilot-only+ bulk invocation commands. Handover brief surfaces both commands under Your Files.
Target environment defaults (macOS SE laptop):
- Assume Bash 3.2 (Apple ships this as
/bin/bash). Nodeclare -A, no${var^^}, no&>. If associative arrays are genuinely needed, use temp-file JSON parsed viapython3/jq. - Assume
python3andjqavailable (both in standard SE install).sfCLI and MCP available in-session only — the SE re-run path usessfCLI.
Salesforce CLI data-write command reference (pin these — do not invent verbs):
At demo-seed scale (handfuls to low hundreds of records — every Scout seed) use the single-record commands. They return clean JSON and need no CSV:
- Create one record:
sf data create record --sobject <Object> --values "Field1=val Field2=val" --target-org <alias> --json - Update one record:
sf data update record --sobject <Object> --record-id <Id> --values "Field=val" --target-org <alias> --json - Query:
sf data query --query "<SOQL>" --target-org <alias> --json
Bulk API 2.0 is for thousands of records and is rarely warranted in a demo seed. If genuinely needed, the verbs are (Bulk API 2.0, sf v2):
- Create / insert:
sf data import bulk(paired withsf data import resume). There is NOsf data create bulk— that verb does not exist;import bulkIS the insert path. - Upsert:
sf data upsert bulk(paired withsf data upsert resume) — requires an external-Id field. - Update:
sf data update bulk. Delete:sf data delete bulk. Export:sf data export bulk. - Bulk commands take CSV input only (not JSON) and one object per call. They run async: the
bulkverb submits a job and returns ajobId; the success/failed record counts and the*-success-records.csv/*-failed-records.csvfiles come fromsf data bulk results --job-id <id>(or the pairedresumecommand) — NOT from the submitting command's immediate output. - Bulk-write success-check therefore reads the job result's failed-record count, NOT the submit command's exit code — a submitted job can exit 0 yet have per-record failures.
Lightning Record Page Field Section — restrictions & rollback (Phase 1)
Full procedure lives under <!-- IF:LRP --> in ${CLAUDE_PLUGIN_ROOT}/prompts/building/phase1.md. This summary is for orchestrator-level decisions and rollback.
Autonomous scope:
- Append fields into the field-bearing leaf Facet of an existing
flexipage:fieldSectionwhose label matches the spec verbatim. Single-column sections: deploy targets the section-body Facet directly. Multi-column sections: spec names a Target column (1-indexed), deploy follows the section-body Facet → flexipage:column componentInstance → column-body Facet, appends there. - LRP composition must be
field_sectionormixedper audit. Re-verified at deploy time via pre-flight grep on retrieved XML. - Audit's
field_sections[].columns[]must carry a non-nullfacet_uuidfor the targeted column — opaque sections route to SE Manual.
Out of scope (skip — SE Manual):
- Adding new field sections, reordering, moving fields between sections / columns, tabset/component edits, dynamic-form regions.
- LRPs classified
record_detail(use classic Page Layout instead),custom, orunretrievable. - Multi-column sections where the spec did not name a Target column.
- Sections where audit reported
facet_uuid: null(opaque column structure).
Rollback:
- The pre-edit FlexiPage XML is captured by the deploy-time retrieve (saved as
.preeditsidecar). Restore the pre-edit XML and redeploy:sf project deploy start --metadata FlexiPage:[Name] --target-org [alias] - There is no
sf project delete source --metadata FlexiPage:[Name]rollback path because deletion would remove the page entirely (catastrophic for a live demo surface). Always restore-and-redeploy.
Flow Rules (Phase 2)
Autonomous-with-SE-gate flow scope matches sf-flow's full trigger spectrum: record-triggered (before-save / after-save / before-delete; any object; cross-object DML allowed), screen flows (see the component whitelist below), autolaunched flows, subflows, scheduled flows, and platform-event-triggered flows. Screen-flow logic complexity (branching, cross-screen reactivity, formula deps) is IN scope, with no hard screen-count cap. Only two things route to SE Manual, neither about complexity: (1) a screen using a component outside the whitelist (no FlowTest signal), and (2) orchestration flows (multi-day lifecycles, not demo-day-viable). If one reaches Phase 2, skip with reason "out of scope for autonomous deploy — SE Manual Checklist." Every autonomous screen flow deploys Draft-first, gated by the happy-path FlowTest — fail twice → stays Draft, never ships live-and-broken.
All Flow Types
- Invoke the
sf-flowskill before generating any Flow XML — it holds the 110-point validation checklist, the full asset template set, and reference guides. - Before generating, skim
${CLAUDE_PLUGIN_ROOT}/skills/sf-flow/references/xml-gotchas.md— root-level alphabetical ordering, fault-connector self-reference, relationship-field traps in recordLookups,storeOutputAutomaticallydata-leak risk. Deployment blockers. - Validate generated XML against the sf-flow checklist. Flag failures in
issues. - Deploy as Draft first (
<status>Draft</status>). Confirm success. - Generate and deploy a happy-path FlowTest XML alongside the flow. Run
sf flow run test --class-names [FlowApiName]_Test --target-org [alias] --json. Pass → activate. Fail twice → skip activation, record inissues— never activate a flow that failed its own smoke test. Per-type FlowTest adaptations live inbuilding/phase2.mdFlow Rules step 4. - Check for existing flows on the same object/trigger via
retrieve_metadata— flag execution order conflicts indiscovery_notes. - Rollback (record in
rollback_commands):sf project delete source --metadata Flow:[FlowApiName] --target-org [alias]PlusQuickAction:[Name]if deployed,FlowTest:[FlowApiName]_Testif deployed.
Record-Triggered Flow
- Templates:
record-triggered-before-save.xml,record-triggered-after-save.xml,record-triggered-before-delete.xml. - Before-delete:
<recordTriggerType>Delete</recordTriggerType>+<triggerType>RecordBeforeDelete</triggerType>. No after-delete flavor exists. - Cross-object DML (trigger on Object A, create/update Object B) is in scope.
Screen Flow
- Template:
screen-flow-template.xml. LWC-embedded variant (screen-flow-with-lwc.xml) is out of autonomous scope. - Whitelisted components: DisplayText, Section, InputField (Text, LargeTextArea, Number, Email, Date, DateTime, Password), Picklist, RadioButtons, Checkbox, CheckboxGroup, MultiSelectPicklist. Any other component → skip with reason "component outside autonomous whitelist."
- Terminal DML: recordCreates, recordUpdates, or recordLookups (specify
<queriedFields>— never<storeOutputAutomatically>in screen flows, per xml-gotchas). - Multi-screen: collect all input across screens first (variables), DML after the final input screen. Each screen breaks the transaction boundary.
- Custom input validation allowed: Boolean formula + custom error message per input.
- QuickAction wiring (if spec requests it): deploy
QuickAction(actionType=Flow), retrieve active layout, add under<quickActionListItems>, redeploy.
Autolaunched Flow
- Template:
autolaunched-flow-template.xml. - No UI, no trigger. Invoked from Apex (
Flow.Interview), subflow, process, or REST. FlowTest exercises via<parameters>block providing input variables.
Subflow
- Stored and deployed as an autolaunched flow; the "subflow" distinction is invocation-pattern only.
- Deploy subflows before their parent in the same phase — parent's static reference fails deploy if the subflow is missing.
- Parent flow exercises the subflow transitively; a dedicated FlowTest on the subflow is still required per the All Flow Types rule.
- Reusable patterns:
${CLAUDE_PLUGIN_ROOT}/skills/sf-flow/assets/subflows/(bulk-updater, dml-rollback, email-alert, error-logger, query-with-retry, record-validator).
Scheduled Flow (Gated)
- Template:
scheduled-flow-template.xml. Built on autolaunched skeleton with a<schedule>block in<start>. - Spec must provide:
<startDate>(YYYY-MM-DD, ≥ demo date unless recurring),<startTime>(HH:MM:SS),<frequency>(Once / Daily / Weekly / Monthly / Yearly / Hourly / Weekdays — FlowSchedule subtype, API v66.0+). Pre-flight: if any field missing in spec, skip. - Optional object filter:
<object>+<filters>for batch-record runs (max 250K interviews/day). - Runs as Default Workflow User.
SCHEDULED_FLOW_DETAILdebug log event confirms record count per run. - FlowTest runs the flow body on-demand; the schedule config is verified via
retrieve_metadataread-back.
Platform-Event-Triggered Flow (Gated)
- Template:
platform-event-flow-template.xml. <start><object>= platform event API name (CustomEvent__eor standard — AIPredictionEvent, BatchApexErrorEvent, FlowExecutionErrorEvent, etc.).- Pre-flight: confirm the event object exists via
retrieve_metadata. If the spec deploys a new platform event in the same run, deploy the event before the flow. - Event references can't directly populate a record variable — create a flow variable per field the flow uses and map in the caller (per Salesforce docs, Paused Flow Interview Considerations).
- FlowTest supplies a mock event payload via
<parameters>blocks, one per referenced event field.
Apex Rules (Phase 2)
Scope: triggers, classes, and invocable actions — multi-class and cross-object
are in scope. No "complexity" cutoff; the gate is the test signal + the bounded
fix-loop (platform-apex-test-run → platform-apex-logs-debug), not a size label.
Author a test class for every class/trigger; a failing / low-coverage test is
recorded in issues and NEVER blocks the deploy (the build ships test-unvalidated
for the SE to finish in Sonnet).
- Invoke
platform-apex-generateskill for generation rules. - Run
run_code_analyzerbefore deploying (if MCP available). Record any high-severity findings inissues. - Rollback commands:
sf project delete source --metadata ApexClass:[ClassName] --target-org [alias]sf project delete source --metadata ApexTrigger:[TriggerName] --target-org [alias]
LWC Rules (Phase 2)
Scope: demo-specific UI — Customer 360 Cards, custom record views, branded components.
- Use MCP LWC expert tools when available (scaffolding, SLDS, validation).
- Run
run_code_analyzerbefore deploying (if MCP available). Record high-severity findings inissues. - Rollback command:
sf project delete source --metadata LightningComponentBundle:[ComponentName] --target-org [alias]
Agentforce Rules (Phase 3)
Two paths depending on whether the agent is new or already exists in the
org. Both use the ADLC skill suite (agentforce-generate,
agentforce-test, agentforce-observe).
New Agent (Agent Script path)
Scope: single agent, topic-based routing with Apex or Flow backing actions.
- Invoke
agentforce-generateskill — follow its "Create an Agent" workflow. - Check for existing agents via MCP
retrieve_metadata— flag conflicts inissues. - Run
run_code_analyzeron Apex backing actions (if MCP available). - Validate via
sf agent validate authoring-bundlebefore publishing. - Preview with
sf agent previewbefore publishing. - Publish, then activate.
- Rollback commands:
sf project delete source --metadata AiAuthoringBundle:[AgentName] --target-org [alias]sf project delete source --metadata ApexClass:[ClassName] --target-org [alias](backing Apex)
Modify Existing Agent (version-safe path)
For agents already in the org (e.g., SDO/IDO pre-installed agents). Every
publish creates a new version; previous versions remain activatable, so
rollback is instant via sf agent activate --version-number N.
- Invoke
agentforce-generateskill — follow its "Modify an Existing Agent" workflow. - Note the current active version number before any changes (rollback target).
- Comprehend existing agent structure, update Agent Spec.
- Validate and preview before publishing.
- Publish (creates new version), then activate.
- Rollback commands:
sf agent deactivate --json --api-name [AgentName] --target-org [alias]sf agent activate --json --api-name [AgentName] --version-number [N] --target-org [alias]
Smoke Test (after activate — both paths)
After the agent is activated, run the official agent test suite using the agentforce-test skill. Prefer Mode B (Testing Center) — build the test-spec.yaml from the spec's Agent test cases and run it:
- Build
test-spec.yamlin the official format (delegate the schema toagentforce-test:basic-test-spec.yaml+guardrail-test-spec.yamlare authoritative). Map each spec test-case row toutterance/expectedTopic/expectedActions(Level-2 invocation names) /expectedOutcome. Include at least one guardrail/off-topic row. Never attach theinstruction_following/conciseness/completenessmetrics (UI crash / score-0 / routing penalty) — rely onexpectedOutcome(LLM-as-judge). - Create:
sf agent test create --json --spec test-spec.yaml --api-name [Suite] -o [alias] - Run:
sf agent test run --json --api-name [Suite] --wait 10 --result-format json -o [alias] - Results:
sf agent test results --json --job-id [runId] -o [alias](use--job-idfrom the run output, NEVER--use-most-recent). Filter the guardrail false-negative: atopic_assertionFAILURE on a row with emptyexpectedTopicis spurious. - If
sf agent testis unavailable, fall back to a Mode Asf agent previewconversational check (start/send/end --authoring-bundle) and record the fallback indiscovery_notes. - Record results in the
smoke_testobject of your JSON output.
A failed test suite does NOT block deployment — the agent is already active. Record failures in issues and flag for the SE. The event-log Action-Invocation Probe (building/sub-agent-validation.md) remains the deterministic gate for hero-action invocation; the suite runs alongside it.
Docs-confirmed UI-only (hard decline — skip with the doc citation)
These Agentforce surfaces have no Metadata API / Agent Script path (docs-confirmed); skip with reason "UI-only — SE Manual Checklist [cite]". They are NOT complexity declines — everything else in a spec is attempted (see CLAUDE.md §Build Boundaries → Docs-Gated):
- Multi-agent orchestration connection wiring (Beta, UI-only) — but Scout DOES author the sub-agent + the parent's
connected_subagentmetadata; only the live connection is UI. Seeprompts/building/agentforce-advanced-capabilities.md. - Custom model / LLM config
- Channel assignment and configuration
- Production-scale test suites (Testing Center batch regression — Mode B) — a scope choice, not a capability limit; functional regression via
sf agent testIS automated in Phase 3.