Coalesce renewal-seed flat deltas into one contract line
Dealops 2 renewal seeding gets an opt-in pricing-spec mode that turns repeated flat delta rows for one SKU into one rep-facing line and fixes ARR-at-scale undercounting.
A new org-level knob: pricingEngineSpec.renewalSeedFlatDeltaCoalesce.
Modes are off, samePrice, and latestAmendmentPrice.
Delta replay can seed one SKU as multiple coincident renewal rows.
TCV stays right, but reps see duplicate lines and computeArrAtScale can keep only the last row’s run rate.
Default mode is off.
Orgs that do not opt in skip the rule entirely, keeping today’s seed behavior unchanged.
Merge Test Org feature-flag allow-lists, first commitment date seeding from the quote start date, an ECM exposure gate, and a knowledge concept doc.
1. Why this exists
accumulateChainProductsemits one product row per chain step.mergeDuplicateContractProductsintentionally leaves flat rows alone.- The rep sees the same SKU twice on the renewal.
- Volume is summed only when the rest of the row payload matches.
- No fields are discarded: features, terms, promotions, overages, and tags must match exactly.
- Ladders and ramps stay out of scope.
computeArrAtScale groups by productSpecId. When every row in the group is fully dated, it treats them as sequential periods and keeps the chronologically last run rate. Coincident rows are not sequential, so ARR can report 25 × $720 instead of 30 × $720; netNewArr inherits the miss.
2. What changes
Core server path
resolveEngagementRenewalSeed reads the mode with getRenewalSeedFlatDeltaCoalesce. latestAmendmentPrice applies repriceFlatDeltasToLatest before assembly; both opt-in modes apply coalesceSamePriceFlatDeltas after product rules.
Meaningful files
apps/server/src/trpc/router/pricingQuote/renewalSeedFlatDeltas.ts+466apps/server/src/trpc/router/pricingQuote/buildEngagementRenewalSeed.ts+40/-1packages/types/v2/pricingSpecData.ts+54renewalSeedFlatDeltas.test.ts+606buildEngagementRenewalSeed.test.ts+323pricingEngineService.spec.ts+56packages/feature-flags/flags.ts+18PeriodTabs.tsx / periodUtils.ts+19/-2knowledge/concepts/renewal-seed-flat-delta-coalescing.md+138| Mode | Input shape | Output shape | Safety rule |
|---|---|---|---|
off |
Any delta replay rows | Same rows | Caller does not invoke the coalescer. |
samePrice |
25 @ $720 + 5 @ $720 |
30 @ $720 |
Whole remaining payload must match; same currency, same price, same window. |
latestAmendmentPrice |
25 @ $720 + 343 @ $600 |
368 @ $600 |
Rows are repriced in chain order before assembly, then merged by the same coalescer. |
3. How it works
describeFlatDeltaRow returns a candidate only for flat, counted, dated rows with currency prices.
- Same
payloadKey: all fields exceptid,commitment_id,quotePriceFlat, andvolumeFlat. - Same currency and price, rounded to
PRICE_EQUALITY_DECIMALS = 10. - Commitment links match, or one row is unlinked.
- Commitment-tier ladders.
tiered/rampedprices.rampedvolumes.- Undated rows or rows whose remaining payload differs.
if (flatDeltaCoalesce !== 'off') {
seed.products = coalesceSamePriceFlatDeltas(seed.products);
}
A land row may be unlinked while its amendment is remapped onto the root commitment. That pair can merge. Two concrete, different commitments cannot merge.
commitment_id: undefinedcommitment_id: c1commitment_id: c1commitment_id: c2The survivor’s emitted commitment_id stays unchanged; only volumeFlat.value changes. Internally, the tracked commitment narrows to the first concrete id so an unlinked row cannot bridge c1 and c2.
The ordering invariant for latestAmendmentPrice
accumulateChainProducts emits head first, amendments later.
Latest means the last row of the line.
Rows are realigned to the renewal window.
Substitution finalizes spec ids and prices.
Rows now share the amendment price.
replicateActiveCommitmentLevel emits commitment-linked rows before unlinked rows. In the Merge shape, the amendment is commitment-linked and the land row is unlinked, so the assembled seed reverses their order. A post-assembly “last wins” read would pick the land’s old price.
4. Tests and rollout guards
coalesceSamePriceFlatDeltas: merge, idempotence, purity, no mutation.repriceFlatDeltasToLatest: latest price, overlapping windows, no cross-currency adoption.getRenewalSeedFlatDeltaCoalesce: defaultoffand explicit opt-ins.
- Replay → reprice → assemble → product rules → coalesce fixtures for Merge ECM scenarios.
- Same-price case:
25 + 5 = 30 @ $720. - Reprice case:
25 + 343 = 368 @ $600, TCV$320,800.
- Two coincident same-spec rows are read as sequential by
computeArrAtScale. - Coalesced row returns the full summed run rate.
netNewArrfollows the corrected ARR.
--expect-exposed=<crmId,...>added to the hierarchy health script.- Fails on both unexpected exposure and missing approved exposure.
- Report is written before the gate exits so failed audits leave evidence.
5. What it doesn't change
- No org opts in implicitly; omitted pricing spec data resolves to
off. - No REST/API surface is added; this is inside the existing Dealops 2 tRPC renewal seeding path.
- No Prisma migration or database schema change is included.
- No generic duplicate-product merge is introduced; flat rows merge only through the new org knob.
- No tier ladder behavior changes; ladder collapse remains owned by existing commitment-tier logic.
- No attempt is made to infer latest price in
samePricemode. - Production deployed org flags are still PostHog-driven; code allow-lists here are for local/default paths.
6. Risks / rollback / open questions
latestAmendmentPrice depends on the chain-order invariant from accumulateChainProducts. The PR documents that invariant and pins it with tests that compare contract-state order against assembled-seed order.
pricingEngineSpec.renewalSeedFlatDeltaCoalesce back to off for the org. The caller then skips reprice and coalesce, restoring today’s row shape.
dealops-jdo7.10.2 stacks on this and carries the account-scoped regression for the production shape.