Plaid v2: turn the approval-level producer ON for the canary diff harness

Flips plaidApprovalLevelV2 for the offline diff harness only, so v2 computes real SBCF_Approval_Level__c values against v1 ground truth — production orgs stay default-OFF.

Author @mehulshinde PR dealops#5763 Base main ← mehul/dealops-a3r Files 3 +/− +747 / −11 Area Dealops 2 · Plaid writeback Risk Canary-only

What it does
Wires the v2 approval-level producer (landed in #5750) into buildHarnessDryRunQliPayload and the harness replay path, so the canary diff harness now emits real L1–L4 levels instead of 0.
What it preserves
The new params default to false/undefined. Every non-harness caller is bit-for-bit identical to main. No prod orgs are opted in.
Observed result
SBCF_Approval_Level__c structural diffs dropped 385 → 176 on the run-13 parity window. Zero engine failures across 30 replayed quotes.
Harness script runPlaidDiffHarness.ts
Writeback PlaidWriteBack.ts
Pricing engine PricingEngineSummary
Producer (#5750) resolvePlaidApprovalLevelForQli

1. Why this exists

The setup

PR #5750 shipped a producer that resolves SBCF_Approval_Level__c for each Plaid QLI by comparing its price to per-product L1–L4 ceilings. The producer is fully tested, but gated behind plaidApprovalLevelV2Enabled, which today is OFF for every org.

The gap

The canary diff harness replays v1 production quotes through the v2 writeback path and compares the payloads. With the flag off, every harness-produced QLI writes SBCF_Approval_Level__c: 0 — so the entire approval-level field shows as a structural diff against v1.

This PR is the smallest possible change that lets the harness exercise the producer end-to-end without touching real orgs: an opt-in param on buildHarnessDryRunQliPayload, set to true only by the harness script.

2. Architecture: where the wiring lives

The harness reconstructs a PricingQuoteInput from v1 Salesforce rows, but it never builds a real OpportunityV2 or runs the pricing engine. The producer, however, reads its ceilings from output.pricingEngineSummary.byProduct[id].variables.{l1..l4}price — which is empty on the harness path. Walk through the steps to see how this PR closes that loop.

3. The three pieces of the change

PlaidWriteBack.ts

Adds two optional params to buildHarnessDryRunQliPayload: plaidApprovalLevelV2Enabled and pricingEngineSummary.

When the flag is on, sets this.plaidApprovalLevelV2Enabled, folds the summary onto fakePricingQuote.output, and calls resolvePlaidApprovalCeilings — mirroring executeWriteBack's setup.

runPlaidDiffHarness.ts

The harness's replayV2QuoteInput now runs PricingEngineSummary.calculateSummary against the reconstructed input, then passes both plaidApprovalLevelV2Enabled: true and the resulting summary into the writeback call.

Uses a supplied canaryPricebookId to avoid needing a real OpportunityV2 row.

harnessApprovalLevel.test.ts

570 lines, 9 Mocha + sinon tests covering: flag-ON resolution (L2 and L4 bands), regression guards that flag-omitted is bit-identical to today, source-level assertions that the harness call site plumbs both params, an e2e path with the real resolver, and tier-wiring.

4. Before / after: buildHarnessDryRunQliPayload

Before (main)
const { pricingQuoteInput,
        organizationId,
        userId = '' } = params;

// ...

const fakePricingQuote = {
  // ...
  input: pricingQuoteInput,
  // output not accessed by Phase 2
  output: {} as PricingQuote['output'],
};

const references =
  await this.resolvePlaidProductReferences({
    pricingQuote: fakePricingQuote, ...
  });

Producer flag stays false, ceilings map is never populated, output is {}. Every harness QLI writes 0.

After (this PR)
const {
  pricingQuoteInput, organizationId, userId = '',
  plaidApprovalLevelV2Enabled = false,
  pricingEngineSummary,
} = params;

this.plaidApprovalLevelV2Enabled =
  !!plaidApprovalLevelV2Enabled;

const fakePricingQuote = {
  // ...
  output: (pricingEngineSummary
    ? { pricingEngineSummary }
    : {}) as PricingQuote['output'],
};

if (this.plaidApprovalLevelV2Enabled) {
  this.plaidApprovalCeilingsByProductId =
    this.resolvePlaidApprovalCeilings(fakePricingQuote);
}

When opted in, mirrors executeWriteBack lines ~460–465. Defaults preserve today's behavior.

5. The "Option B" decision: where ceilings come from

The PR description and inline test comments call this out explicitly. There were two ways to get real L1–L4 ceilings into the harness:

OptionApproachVerdict
A (rejected) Have the harness build a real OpportunityV2 row on the canary org, then go through PricebookController the way production does. Heavy. Needs DB writes per replay.
B (chosen) Run PricingEngineSummary.calculateSummary directly against the reconstructed input, with a synthetic opportunity and a supplied canaryPricebookId. Pass the resulting summary into the writeback call. The ceiling-variable path (l1..l4price) reads only DataPoints + pricingSpec keyed by (productId, pricebookId, tier)opportunityV2Data is not load-bearing.

The synthetic opportunity in replayV2QuoteInput uses id: '__harness_synthetic__' and an empty custom: {} map — explicitly fine because the producer never reads it.

6. Failure handling

Graceful degradation. If getPricingSpec, getDataSheet, the pricebook lookup, or calculateSummary throws, the catch block logs a warning and leaves pricingEngineSummary as undefined. buildHarnessDryRunQliPayload then sees an empty output: {}, ceilings resolve to an empty map, and the producer returns level 0 for every QLI on that quote. Per-quote replay_failure plumbing is untouched — one bad quote does not abort the canary run.

7. Canary results on the run-13 parity window

Approval-level diffs 385 176 −54% vs pre-wiring baseline
Total structural diffs 2,603 1,425 same window, same split
Engine failures 0 / 30 across all replayed quotes
Residual attribution ~94% predicted v1-parity cosmetic bucket

Spot-checks confirm the remaining "v2 = 0" lines are legitimate ramped resolutions, not silent fallback. The ~94% residual is v1 omitting SBCF_Approval_Level__c on multidim/segmented lines while v2 emits a value — tracked separately, mirroring the carve-out from #5755.

8. Tests, in detail

TestAsserts
flag ON → level 2 (flat, price 700)Producer resolves price 700 against {l1:1000, l2:800, l3:600, l4:400} as level 2.
flag ON → level 4 (flat, price 300)Below the deepest ceiling resolves to L4.
flag OMITTED → level 0Regression guard: default path is bit-identical to main.
flag ON → resolvePlaidApprovalCeilings invokedVerifies the ceilings map gets populated before the producer runs.
flag OMITTED → resolver NOT invokedOff-path regression guard.
harness source: plaidApprovalLevelV2Enabled: trueSource-level regex check on runPlaidDiffHarness.ts.
harness source: calculateSummary + pricingEngineSummary plumbedCatches the "param accepted but never propagated" regression class.
e2e: real resolver + injected summary → level 2Closes the false-green gap a naive wiring would sail through.
e2e: tiered product → tier child QLIs carry correct levelsTier-1 (price 750) → L2; Tier-2 (price 300) → L4.

Note: replayV2QuoteInput is module-private and the live path does real SF/engine reads, so its contract is pinned with source-string regex checks — same pattern as the beadops-bvv.2 test in PlaidWriteBack.mm.test.ts.

9. What this doesn't change

10. Risk & follow-ups

Risk: low. Default-OFF for all real orgs. The only behavioral change is on the local/canary diff-harness path. The producer math is already proven by PlaidWriteBack.approvalLevel.test.ts; this PR only pins the wiring.
Tracked follow-ups (not blockers).