DocSWS-01
FiledRevenue infrastructure
Revision2026.05
ScopeSalesforce-native
Build1 afternoon · 22 May 2026
StatusIn sandbox

Some Salesforce actions can't be undone. So AI has to earn the right to take them — one approval at a time.

A Salesforce-native decision surface for the moment AI agents start doing real work — keeping humans in the loop while the system learns which patterns it can take over. Built so trust compounds in one durable place, not a hundred Slack threads.

01 / Demo

Interactive demonstration.

Fig. 01

A real merge case — irreversible, destructive, the kind of action a trust system has to handle well. Approve or deny the card directly, or load one of the three scripted scenarios on the right to drop into a specific moment of the trust lifecycle. The Pattern_Stats__c panel updates in real time. (Thresholds compressed for demo — the deployed system uses 20 approvals / 3 denials.)

How to read this card
CASE-00284921 · PTN-ACCOUNT-DUPMERGE
UNPROVEN

Merge two duplicate Account records for Acme Industries.

Two records appear to be the same company — same domain, same DUNS, same billing address, variant legal name. Older record survives.

Pattern
PTN-ACCOUNT-DUPMERGE First time you've seen this
Evidence
Match same domain · same DUNS Variants "Acme Industries" · "Acme Industries, Inc." Activity 174 events, 0 conflicts
Executes
merge_accounts(survivor='001…abc', dupe='001…def', strategy='survivor_wins')
This action is irreversible. Merge consolidates references onto the survivor; the duplicate record is removed.
Auto-resolve · active Future cases matching this pattern execute without human review.
Pattern self-disabled. Three denials in 30 days — alert Task created for ops review. No future cases route to this pattern until a human re-approves it.

Survivor preserved · Logged to audit · You own the outcome.

Guided tour Step 0 of 5

Walk through how trust works on this pattern. Click Approve to begin — the system will react after each decision.

Fig. 01 Decision card with live trust signature, three-scenario picker, and the underlying Pattern_Stats__c record. Every approve / deny / pause is one row update.

Try this: Free-play the merge directly, or load one of the three scenarios. Graduation walks a fresh pattern up to auto-resolve. Reversal drops you into a pattern that's been silent for 32 days, surfacing a 5-record multi-merge that breaks the baseline. Self-disable hands you a pattern with two prior denials — one more and it steps back. The Pattern_Stats__c record on the right is the same shape the deployed system uses; every reinforce/weaken/pause is one row update.
02 / Loop

The feedback loop.

Fig. 02 · Tbl. 01

The card you just played with is one slice of a closed loop. Five stages, repeating per case, accumulating per pattern. The same loop runs whether the action is reversible or destructive — only the surface treatment changes.

  1. Stage 01

    Match

    A new case arrives. The matcher checks Pattern_Definition__c rules and tags it with the matching pattern's ID.

    trigger · async
  2. Stage 02

    Surface or skip

    If the pattern is anything other than validated, the card surfaces for human review. If validated, the executor runs silently and writes an audit row.

    route · < 1s
  3. Stage 03

    Decide

    Human approves or denies. The decision fires reinforce() or weaken() — one optimistic-locked row update on Pattern_Stats__c.

    write · 1 row
  4. Stage 04

    Threshold

    If consecutive ≥ 20 (5 in demo): auto_resolve flips true. If denials ≥ 3 in 30 days: is_deactivated flips true and an alert Task is created.

    state machine
  5. Stage 05

    Route forward

    The next matching case enters Stage 01 again. Whether it surfaces or executes silently depends on the trust state this loop just updated.

    loop back

Fig. 02 One pass through the loop. The pattern fires per case; the count accumulates per pattern. Stage 04 is the trust threshold check — graduation, weakening, or deactivation.

Five stages, one closed loop. Trust accumulates in Pattern_Stats__c the same way it would in your head — repeated correct outcomes earn discretion, denials revoke it. The system isn't trained; it's shaped, one human decision at a time.

Action surface.

A Decision Surface card can drive any of the actions below. The card's shape stays the same; what changes is the irreversibility chrome — a soft fine-print line for reversible actions, an always-on warning for destructive ones.

Action Reversibility Card treatment Scope
reassign_owner Reversible · 30 days Standard card. Undo path in fine print. Owner change on Account/Opp/Lead. 1–25 records
update_field Reversible Before/after values shown inline in the Executes row. Schema-bounded. 1–1k records
status_transition Reversible Downstream automations listed before approval — validation rules, flows, process builders. 1 record
add_to_list Reversible Territory, list, campaign membership. Easy to undo. 1–100 records
convert_lead Semi-reversible "Created records" preview shown — converting creates Account, Contact, and Opportunity. 1 record
approve_quote Semi-reversible Downstream commitments enumerated — DocuSign envelopes, contract terms, billing triggers. 1 record
merge_records Irreversible Always-on irreversibility warning. Survivor preserved. Higher graduation threshold for this class (30 vs 20). 2–N records
delete_record Effectively irreversible 15-day soft-delete window surfaced. Recycle-bin restoration linked. Hard delete after window. 1–N records
send_external Irreversible Third-party destination and full payload shown verbatim. Email, webhook, API call — cannot be unsent. 1+ records

Tbl. 01 Action surface. All patterns can earn autonomy; reversible actions graduate at 20 consecutive approvals, irreversible ones at 30. The pre-graduation card includes an additional confirmation step for irreversible actions.

03 / ADR

Architecture decision record.

vii. articles

How the system was framed, what was at stake, the design choices, and what it cost not to take shortcuts.

i.The problem.

An internal ops team was drowning. The same handful of case types — reassign this AM, merge these two accounts, add a location, link a dashboard, investigate this — were eating three to five minutes each, hundreds of times a week. The work was tedious, but it wasn't simple: merges are irreversible, account-manager reassignments touch compensation, any of these can silently break a customer's reporting if executed against the wrong record.

The obvious answer was "automate it." The honest answer was: not yet. Some actions can't be safely automated until the system has proven itself correct enough times that the cost of a mistake is dominated by the savings. Until then, the right move is to assist the human — not replace them.

"Automation isn't a switch you flip when something is repetitive. It's an outcome you earn after demonstrating you're correct."

ii.The insight.

Trust is a signal, not a switch. The system should be allowed to act unsupervised only on patterns where it has accumulated evidence of correctness — and the evidence has to come from the people whose work it's affecting. Every human decision becomes data: an approval reinforces the pattern, a denial weakens it. Patterns that earn enough consecutive approvals graduate to autonomy. Patterns that accumulate denials self-disable and ring a bell.

A pattern that has handled 247 cases without a denial should look different from a pattern that hit its first denial yesterday. The visual treatment carries the trust metadata — the five-dot signature, the case meta line, the conditional banner — so the human approver knows, at a glance, how much weight to give the system's recommendation.

iii.The architecture.

One case → one pattern lookup → one decision card → one human input → one stats update → maybe one queued action. Everything else is plumbing.

The matcher (CasePatternMatcher) and the stats service (PatternStatsService) are pure Apex with no UI awareness. The card is a pure Lightning Web Component — asks four questions, shows what the system found, emits an event. The Queueable executor is the only place that writes; it runs asynchronously, chains itself for batches over 200, and re-queries after each write to verify the change landed before declaring success.

The whole trust model lives in seven fields on one custom object: Pattern_Stats__c. Every reinforce/weaken is a single row update under optimistic FOR UPDATE locking. Nothing's distributed. Nothing's eventually consistent. The state of the world fits in one row, and that row is the source of truth for whether the next case surfaces or runs silently.

case arrives · trigger CasePatternMatcher Apex · pure · stateless regex + evidence weighting Decision Card (LWC) pure view · emits an event visual trust language Human approves / denies decision authority approve → ← deny reinforce() consecutive++ · approvals++ weaken() denials++ · consecutive=0 Pattern_Stats__c FOR UPDATE · single row · seven fields source of truth decayStale() Schedulable · 90-day sweep old trust isn't trust — it's habit if auto_resolve OR human approved CaseResolver (Queueable) async · chains over 200 · post-write verify executes + verifies case closed · chatter logged 3 denials → self-disable 5 in a row (demo) → auto_resolve FIG. 03 · TRUST PIPELINE
Edge stub (entry / exit) System node (Apex / LWC) Human-in-the-loop
Fig. 03 The trust pipeline. Every case routes through the same five stages — match, surface, decide, record, execute — with Pattern_Stats__c at the center as the single durable source of truth. The 90-day decayStale() sweep is the only thing that writes outside the decision path. Threshold compressed to 5 for the demo; the deployed system uses 20 for reversible patterns and 30 for irreversible ones.

iv.Visual trust language.

The card never says "trust me, I'm 87% confident." Confidence scores are vibes; provenance is not. The trust signature — five dots and a label — maps directly to conditions in Pattern_Stats__c. The design is the data.

Signature State Condition What the human reads
Unproven No approvals yet No track record. Read the case the way you'd read a contract.
Building 1–2 consecutive approvals Early evidence accumulating. Still worth scanning end-to-end.
Proven 3+ consecutive approvals Confidence is earned. Scan-and-approve is fair.
Validated · auto-resolve ≥ 20 consecutive (5 in demo) Future cases run without you. This view is a courtesy.
Weakened Recent denial · streak broken Oxblood dots. Something failed recently — don't approve on autopilot.
Deactivated 3 denials in 30 days System has stepped back. Human-only until a human re-approves.

v.Safety mechanisms.

The point of automation is to save human time. The point of safety is to make sure the time saved is worth more than the mistakes you absorb. Six guards work together — each one cheap on its own, expensive in aggregate to bypass.

Optimistic locking on stats updates

Pattern_Stats__c is queried FOR UPDATE before reinforce/weaken. Two simultaneous approvals on the same pattern can't both increment.

Irreversibility warnings

Merges show a separate confirmation step that names the surviving record, lists the shared contacts being resolved pre-merge, and requires a second click. The card refuses to render a merge action without this.

Graduated autonomy

Reversible actions graduate at 20 consecutive approvals; irreversible ones (merges, hard deletes, external sends) graduate at 30. No fear exception — only a proportional trust curve. Self-disable still fires at 3 denials regardless of class.

Self-disabling patterns

Three denials in 30 days flips is_deactivated=true and creates an alert Task. The system can't quietly keep being wrong.

Post-execution verification

Every Queueable re-queries after writing, confirms the field landed, and only then marks the case resolved. If verification fails, the case reopens with the failure reason on it — silence is never the answer.

90-day trust decay

A Schedulable sweep clears auto_resolve on any pattern that hasn't seen a confirmation in 90 days. Old trust isn't trust — it's habit.

vi.The launch state.

Note · Built from scratch in a single afternoon (see deploy log in §03). Of 741 yearly support cases, 396 (53%) match a defined pattern — reduced to a one-click approve / deny on the card. 166 of those (22% of total volume) are auto-decidable and clear the graduation threshold immediately on 12 months of seed data — Merge_Duplicate (103 closed, 94% success) and Reassign_AM (52 closed, 93% success). They run silently at launch. The remaining six pattern types route to humans until they earn the same.

53%
Decisions reduced to one click live
396 of 741 yearly cases match a defined pattern. The card turns "what is this and what should I do?" into "approve or deny."
22%
Volume auto-resolved at launch live
166 cases. Merge_Duplicate + Reassign_AM seeded above threshold from 12 months of historical evidence — zero clicks required.
20 / 30
Graduation thresholds by design
Reversible actions earn autonomy at 20 consecutive approvals; irreversible ones at 30. The bar scales with what you can't take back.

What this earns: nobody gets handed an "AI did it" mystery error. Every auto-resolved case has a verifiable trail back to prior human approvals on the same pattern, and a post-execution re-query proving the write stuck. The ops team doesn't lose work — they lose the work that wasn't a decision in the first place.

vii.The stack.

  • Surface · LWC Decision card. Single component, four questions, no business logic. Emits approve / deny events.
  • Routing · Apex CasePatternMatcher. Regex over Subject + Description, ordered by specificity. Pure function, unit-tested against the corpus.
  • Learning · Apex PatternStatsService with FOR UPDATE locking. Flips auto_resolve on graduation, is_deactivated on the third denial.
  • Execution · Queueable All writes async. Batches over 200 chain a second Queueable. Each write is followed by a re-query confirming the field stuck.
  • Memory · SObject Pattern_Stats__c. One row per pattern. Seven fields. The whole trust model lives here.
  • Decay · Schedulable Nightly sweep clears auto_resolve on any pattern with last_decision_at older than 90 days.
What I take from this

Trust compounds — most people just underinvest in it.

The payoff is slow and invisible, which is why most decision surfaces are designed against trust rather than for it. What stops happening: the same case stops surfacing forever, and the unfamiliar ones stop hiding inside a queue full of routine.

What's next: A RevOps prioritization engine on the same trust architecture — surfacing what to build, what to defer, and what to retire. In progress.
Back to portfolio →