sf-workflow-orchestration
Skill2 starsChanged 2 months agoMITView on GitHub
Runs Salesforce delivery as a five-wave parallel agent workflow with deterministic gates. Use when a story, bug, or refactor touches more than one metadata type, when several agents must work at once without colliding, when deciding which wave a task belongs to, when a gate fails and the wave must abort, or when wiring the vf-check runner, the vibe-force hooks, and the .vibeforce state files into a pipeline from local edit to verified production deploy.
In this repository34 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- sf-agentforce-developmentSkill
- sf-apex-developmentSkill
- sf-apex-testingSkill
- sf-async-apex-patternsSkill
- sf-cli-operationsSkill
- sf-code-analyzer-qualitySkill
- sf-data-cloudSkill
- sf-data-managementSkill
- sf-debugging-logsSkill
- sf-deployment-strategiesSkill
- sf-fflib-domain-service-uowSkill
- sf-fflib-foundationsSkill
- sf-fflib-operationsSkill
- sf-fflib-selector-layerSkill
- sf-fflib-testingSkill
- sf-flow-automationSkill
- sf-governor-limitsSkill
- sf-integration-patternsSkill
- sf-local-developmentSkill
- sf-lwc-developmentSkill
- sf-lwc-jest-testingSkill
- sf-minimal-changeSkill
- sf-org-security-auditSkill
- sf-packaging-releaseSkill
- sf-post-deploy-verificationSkill
- sf-process-builder-migrationSkill
- sf-project-structureSkill
- sf-scratch-orgs-sandboxesSkill
- sf-security-modelSkill
- sf-setup-automationSkill
- sf-soql-sosl-optimizationSkill
- sf-technical-debt-auditSkill
- sf-ui-test-automationSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 1 is distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 51
One batch per wave: All agents of a wave are dispatched in a single parallel batch.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Salesforce workflow orchestration
The unit of work is a story: one user-visible behaviour change, delivered through five waves. Waves 1, 2 and 4 run several agents at the same time; waves 0 and 3 are serial because they produce a decision the others depend on.
Nothing in this skill is advisory decoration: every wave boundary is a machine-checked gate
(vf-check), and the file-collision rules are enforced by the pre-edit-guard hook, not by
politeness.
When to use
| Situation | Use this skill |
| Story touches Apex + LWC + metadata | Yes: full five-wave run via /vf-story |
| Single-file typo fix, one metadata attribute | No: fix it, run vf-check static --changed |
| Bug with unknown root cause | Wave 0 only first (sf-scout), then decide |
| Production incident | Waves 3-4 only, with a human in the loop on every step |
| Refactor with no behaviour change | Waves 1-2, plus a diff review through /vf-review |
| Package release | Waves 3-4 plus skill sf-packaging-release |
Wave model
wave 0 scope sf-scout (read-only) -> impact map
design sf-technical-architect (read-only, when the story has a real choice)
-> .vibeforce/state/architecture.md
decide orchestrator -> .vibeforce/state/contract.md
wave 1 build sf-apex-engineer \
sf-lwc-engineer | one parallel batch, disjoint owned paths
sf-metadata-engineer |
sf-integration-engineer/
wave 2 check sf-test-engineer \
sf-quality-gate | one parallel batch, read-mostly
sf-security-reviewer /
gate vf-check local -> must pass
wave 3 deploy sf-deploy-engineer (serial)
gate vf-check deploy-validate -> deploy-quick
wave 4 verify sf-org-verifier \ one parallel batch
sf-test-engineer /
gate vf-check verify -> verdictRules that make the parallelism safe:
- One batch per wave. All agents of a wave are dispatched in a single parallel batch. Dispatching them one at a time is a defect, not a style choice: it serialises the wave and doubles the wall clock.
- Disjoint ownership. Each wave-1 agent owns metadata paths no sibling may write. The
pre-edit-guardhook denies a cross-slice write and names the owning agent. - Contracts before code. Anything two agents both depend on (Apex method signature, field
API name, event payload, permission set name) is decided in wave 0 and written to
.vibeforce/state/contract.md. Agents read it; they never negotiate mid-wave. - No mid-wave validation. Wave-1 agents do not run the project-wide gate; they would block on each other's half-finished edits. Checks belong to wave 2.
- Gates are blocking. A wave starts only after the previous wave's gate returned exit 0.
Wave 0: scope, design, contract
Serial, read-only, cheap relative to what a wrong design costs in wave 1. Each step feeds the next.
# what the story touches, before any edit
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" static --changed # baseline: is the tree already clean?
git log --oneline -10 -- force-app/main/default/classes # recent churn in the areaStep 1 - sf-scout returns an impact map: metadata files in scope, existing tests covering
them, triggers and flows already on the affected objects, integration touch points, and risks.
Step 2 - sf-technical-architect, only when the story has more than one defensible design.
It gets the story and the scout map, and returns decisions with the rejected alternative and the
binding limit for each. Run it when the story:
| Trigger | Example |
| changes the data model | a new object, a relationship, a field that carries volume |
| changes who sees what | OWD, sharing rules, Apex sharing, restriction rules |
| crosses a system boundary | a callout, an inbound API, an event, middleware, identity |
| states a non-functional number | row counts, latency, retention, availability |
| forces a declarative-versus-code call | Flow or trigger, rollup or Apex, External Services or hand-written callout |
| changes packaging or environments | a new package, a changed promotion path |
Skip it for a typo, a single-file fix, or a story whose design the contract already fixed. An architecture run on a story with one defensible design returns one line and costs a turn.
Step 3 - the orchestrator applies the minimal change ladder (skill sf-minimal-change) and
records the outcome in the contract file: which rung each requirement landed on, which alternative
was rejected and why. Scope that does not survive the ladder never reaches wave 1. The architect's
Contract inputs go in verbatim; its full record is persisted to
.vibeforce/state/architecture.md so wave 2 can review against the decision, not against taste.
Contract file shape (full template in references/contract-file.md):
## Story
As a service agent I need the case escalation reason on the case list.
## Decisions
- Escalation reason: existing field Case.Escalation_Reason__c reused (rung 2), no new field.
- List UI: lightning-datatable inside existing caseList LWC (rung 4), no custom table.
- Validation: validation rule Case.Escalation_Reason_Required (rung 3), no Apex.
## Contracts
- Apex: CaseEscalationService.escalate(List<Id> caseIds, String reasonCode) -> List<EscalationResult>
- Field API: Case.Escalation_Reason__c (picklist, values: Sla_Breach, Customer_Request)
- Permission set: Case_Escalation_Access (field read/edit + Apex class access)
## Ownership
- sf-apex-engineer: classes/CaseEscalationService*.cls, classes/CaseEscalationServiceTest.cls
- sf-lwc-engineer: lwc/caseList/**
- sf-metadata-engineer: objects/Case/**, permissionsets/Case_Escalation_Access.permissionset-meta.xmlWave 1: parallel build
Dispatch every needed engineer in one batch. Each gets: the story, the contract file, its owned paths, and its non-goals. Typical split:
| Agent | Owns | Never touches |
sf-apex-engineer | **/classes/**, **/triggers/** | classes/integration/**, LWC, object metadata |
sf-lwc-engineer | **/lwc/**, **/aura/**, **/staticresources/** | Apex, metadata XML |
sf-metadata-engineer | **/objects/**, **/permissionsets/**, **/flows/**, **/layouts/**, **/flexipages/**, **/labels/**, Agentforce and Data Cloud definitions | Apex, LWC, named credentials |
sf-integration-engineer | **/namedCredentials/**, **/externalCredentials/**, **/externalServiceRegistrations/**, **/externalClientApps/**, **/platformEventChannels/**, classes/integration/** | everything else |
Each agent writes its own tests as part of the build (*Test.cls, __tests__/*.test.js) and
runs only the narrow check for its own files, for example:
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" jest --files force-app/main/default/lwc/caseListHook support during this wave:
post-edit-checkclaims every written path for the editing agent and records it in the session touch list.pre-edit-guarddenies a write to a path another live agent claimed, and denies cross-slice writes with the owner's name in the reason.subagent-stop-releasefrees the claims when an agent finishes, so wave 2 is unobstructed.
Wave 2: parallel checks
Three agents, one batch, over the same tree:
| Agent | Runs | Fails the wave when |
sf-test-engineer | vf-check jest, vf-check apex --target-org <dev> | coverage below apexOrgCoverageMin/apexClassCoverageMin/jestCoverageMin, or any test fails |
sf-quality-gate | vf-check static | a finding at or above analyzerFailSeverity |
sf-security-reviewer | read-only review against skill sf-security-model | missing CRUD/FLS or sharing enforcement, secret in source, injection path |
The wave gate is the composite local check:
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" local --changedlocal = format + lint + analyzer + jest. It needs no org, which is why it is the gate
that runs on every turn: the stop-local-gate hook re-runs the configured gate over the files
touched in the session and refuses to end the turn while it fails.
Fix rule: failures are fixed at the source by the owning wave-1 agent. Thresholds are never lowered, assertions are never weakened, and findings are never suppressed to pass a gate.
Wave 3: serial deploy
One agent, one org at a time, always validate before deploy.
# 1. check-only validation, runs the tests in the target org without committing anything
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" deploy-validate --target-org acme-uat
# 2. deploy the already-validated job, no re-run of tests
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" deploy-quick --target-org acme-uatdeploy-validate records the job id in .vibeforce/state/deploy-jobs.json; deploy-quick
refuses to run without a matching validated job for that org. For production aliases the
pre-bash-guard hook denies sf project deploy start outright and forces the
validate + quick-deploy path; the direct command becomes available only with an explicit human
decision (VF_ALLOW_PROD=1). Details in skill sf-deployment-strategies.
Promotion order is fixed: dev -> integration -> uat -> prod. A wave-3 failure never gets
"fixed forward" in the target org by hand; it goes back to wave 1.
Wave 4: parallel post-deploy verification
The deploy succeeding is not the story working. Two agents, one batch:
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" smoke --target-org acme-uat
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" apex --target-org acme-uat --tests CaseEscalationServiceTestsf-org-verifier runs the smoke probes (deploy report, anonymous-Apex probes, verification
queries, limits, error-log scan) and collects diagnostics into .vibeforce/reports/.
sf-test-engineer runs the targeted org test set. The verdict table and the forward-fix versus
rollback decision are covered in skill sf-post-deploy-verification and in
references/failure-and-rollback.md.
Gate and hook map
| Gate | Command | Enforced by | Blocks |
| Baseline clean | vf-check static --changed | wave 0 | starting on a dirty tree |
| Local gate | vf-check local --changed | stop-local-gate hook, wave 2 | ending a turn with failing source |
| Org test gate | vf-check apex --target-org <alias> | wave 2/4 | deploying untested behaviour |
| Validation gate | vf-check deploy-validate | wave 3, pre-bash-guard | unvalidated production deploys |
| Verification gate | vf-check verify | wave 4 | declaring done without org evidence |
| Ownership | claim file in .vibeforce/state/ownership.json | pre-edit-guard, post-edit-check | two agents writing one file |
| Secret guard | content patterns | pre-edit-guard | credentials entering the repo |
| Destructive guard | command patterns | pre-bash-guard | prod data/metadata deletion |
Hook modes: off, minimal (deny-only guards), standard (default: guards + advisory notes +
stop gate), strict (also denies deploying without a passing local gate). Set
hooks.mode in .vibeforce/config.json or VF_HOOK_MODE per shell.
Anti-patterns
| Anti-pattern | Why it breaks | Instead |
| Dispatching wave-1 agents one by one | no parallelism, doubles wall clock, invites drift between slices | one batch, disjoint paths |
| Letting two agents share a file "carefully" | last write wins, silent loss; the hook denies it anyway | split the file or serialise that edit through one owner |
Running vf-check local inside wave 1 | fails on a sibling's half-written file, agents block each other | check in wave 2 |
| Negotiating a method signature mid-wave | both sides stall or diverge | decide it in wave 0, write it to the contract |
sf project deploy start to production | no validated job, no quick deploy, full test run in the release window | validate + quick deploy |
| Treating deploy success as done | metadata deploys fine and the feature still fails on permissions or data | wave 4 |
| Lowering a gate threshold to finish | the gate stops meaning anything | fix the source, or get an explicit human decision |
| Skipping wave 0 for a "small" story | the small story turns out to touch a trigger, a flow and a permission set | scout first; it is cheap |
Verification
# hook engine behaves as specified (runs in this repository)
node --test tests/
# the gate the Stop hook runs, on the current change set
node "${CLAUDE_PLUGIN_ROOT}/scripts/checks/vf-check.mjs" local --changed
# state the orchestrator relies on
cat .vibeforce/state/contract.md
jq . .vibeforce/state/ownership.json
jq '.jobs[-1]' .vibeforce/state/deploy-jobs.json
ls -1 .vibeforce/reports | tail -5A wave is complete when: its gate returned exit 0, every owned path is released, and the hand-off report lists changed files, published contracts, check results and residual risk.
References
references/wave-playbook.md- per-wave dispatch briefs, inputs, hand-off formats.references/ownership-matrix.md- path-to-agent map, claim lifecycle, conflict resolution.references/gates-and-hooks.md- every hook, every mode, exit codes, escape hatches.references/contract-file.md- contract template, decision log, worked examples.references/failure-and-rollback.md- abort conditions per wave, forward-fix vs rollback.references/external-skills.md- where Salesforce-authored plugins fit in the waves, who owns generated metadata, DevOps Center versus CLI promotion.
Related skills: sf-minimal-change, sf-deployment-strategies, sf-post-deploy-verification,
sf-apex-testing, sf-lwc-jest-testing, sf-code-analyzer-quality, sf-security-model,
sf-cli-operations, sf-project-structure, sf-agentforce-development, sf-data-cloud.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

