Salesforce L2A Governed Matcher
Private BetaPre-conversion account context for Salesforce with audit-safe apply. Init emits a downstream automation risk audit, scout produces disagreements against the incumbent field, and apply writes only to a narrow Gremlin-owned Lead surface with plan-hash confirmation and receipts. The playbook below describes the current pilot surface; broader availability follows pilot feedback.
The Slack Message
Our L2A field feeds assignment rules and territory. I don't trust it but I cannot touch it until we prove what changes if we do. Can you show me what Gremlin would do differently without writing anything, and let me approve before any field moves?
The Prompt
Kicked off from the terminal with mode and risk posture spelled out.
We have 50K open Leads in Salesforce and our incumbent L2A field (Account_Match__c) is feeding assignment rules. I don't know if I can trust it. I need to: 1. Scan the org for downstream automation that references Account_Match__c 2. Run Gremlin salesforce l2a in observe_existing mode against a 1K sample 3. Hand the RevOps team disagreements.csv and the blind-spot digest 4. After they sign off, dry-run the fix plan and apply only the safe Gremlin-owned writes No OwnerId writes, no territory, no conversion. Nothing touches Account_Match__c until we've acknowledged the risk audit.
The risk surface is not the field — it is the automation
Writing a matched-account field can trigger assignment rules, record-triggered Flow, territory logic, and account-side updates. That is why init emits a downstream automation risk audit and observe_existing is the default entry mode. Init → scout → disagree → dry-run → apply. Nothing customer-owned changes without an acknowledged risk hash.
Core Workflow
Init, scout, review, dry-run, apply. Dry-run is the default on every write path.
Init + Risk Audit
Scan Apex, Flow, assignment rules, and validation rules for references to the incumbent field. Emit risk_audit.md before any write mode is locked.
Scout in observe_existing
Evaluate open leads deterministically, compare against the incumbent field, and emit grouped exceptions and a hashed fix plan.
Disagreement Review
Hand disagreements.csv, blind_spot_digest.md, and grouped_exceptions/ to RevOps. Decision codes replace threshold arguments.
Dry-Run Fix Plan
Revalidate preconditions, emit APPLY_DRY_RUN_OK per row, and surface any precondition drift since scout ran. Nothing changes yet.
Apply with Plan Hash
Promote to live writes with --confirm-plan-hash, --ack-risk-audit, --max-actions, and --max-per-account. Receipts on every row.
"50K open Leads, incumbent field Account_Match__c feeds assignment rules. The risk surface is not the field — it is the automation that wakes up when the field changes. Start with init in observe_existing so no customer field is written until the risk audit is acknowledged."
"Step 1: init --mode observe_existing, scan downstream automation. Step 2: scout on 1,000-lead sample. Step 3: review disagreements.csv and blind_spot_digest.md. Step 4: trace ambiguous rows. Step 5: dry-run fix_plan.json. Step 6: apply with caps."
"Account_Match__c is high_risk — confirmed. Observe_existing is the correct entry mode. Now scout a 1K sample against open leads."
"214 disagreements against the incumbent field. That is the artifact RevOps actually needs. Trace a disputed row before handoff."
Artifacts ready for RevOps: summary.md, scout_summary.json, disagreements.csv (214 rows), safe_matches.csv (653 rows), grouped_exceptions/, blind_spot_digest.md, fix_plan.json (plan_hash 9f2c...e104, 653 actions).
The Disagreement Queue
This is what RevOps sees. Each row carries a decision code, candidate account, and the incumbent value. Operators mark rows for apply or escalate them to manual review.
| lead_id | gremlin_decision_code | existing_field_value | agreement | operator_action | |
|---|---|---|---|---|---|
| 00Q5g000011AAA1 | [email protected] | L2A_SAFE_EXACT_DOMAIN_SINGLE_ACCOUNT | 001xx000003DEF9 | disagree | apply_gremlin_match |
| 00Q5g000012BBB2 | [email protected] | L2A_REVIEW_DOMAIN_MULTI_ACCOUNT | 001xx000003ABC1 | disagree | manual_review |
| 00Q5g000013CCC3 | [email protected] | L2A_SAFE_KNOWN_ACCOUNT_MAP_SINGLE_ACCOUNT | null | disagree | apply_gremlin_match |
"RevOps reviewed disagreements.csv. They want to apply only the gremlin_owned writes — no changes to Account_Match__c. That means mode stays observe_existing and the fix plan only fires lead.set_gremlin_match and lead.set_gremlin_state. Risk audit hash acknowledged separately."
"Dry-run looks clean. 5 rows drifted — that is expected for a live org. Apply with caps: --max-actions 100 for the first batch to validate permissions and receipts before scaling."
First 100 actions applied with receipts. 0 failures. Account_Match__c untouched. Gremlin_Matched_Account__c, Gremlin_Decision_Code__c, Gremlin_Receipt_Id__c now populated on 100 leads. Remaining 548 actions ready for the next batch.
Safety Guarantees
What This Playbook Will NOT Do
Non-goals are enforced by the CLI, not just documented. Any drift into these lanes moves the product from governed matcher to routing platform.
Requirements
Salesforce Connected App
Read Lead and Account; write Gremlin-owned Lead fields only
Gremlin CLI with l2a module
g-gremlin salesforce l2a init | scout | trace | apply
gremlin.l2a.yaml
Emitted by init — drives mode, fields, and fingerprint
Risk audit acknowledgment
--ack-risk-audit hash required for shared_existing live apply
Results
Account_Match__c remained read-only; no assignment-rule side effects fired.
apply_receipt.json carries plan hash, decision code, and before/after for every row.
Request pilot access
The Salesforce L2A module is in private beta with a limited pilot cohort. Start conversations with init --mode observe_existing against a sandbox — the risk audit and disagreement report carry the story before any field is touched.
Related: Salesforce Lead-to-Account Matching guide · LeanData vs audit-first L2A · Salesforce dedupe playbook