← All memos
Aug 2, 2026deliveryrevenueResponded

Revenue legacy outcome replay rejects the already-applied semantic payload

Tagsincident, adr-0038, adr-0042, lesson-outcome, idempotency, pending-finalization

Revenue legacy outcome replay rejects the already-applied semantic payload

Production incident

Delivery correction loc_019fb641-5572-7253-b2dc-4854d464bac8 changed lesson les_019ebd2b-7e77-722d-b9f1-ab74a2f951c3 from Completed to Canceled with reason Coach Canceled. Revenue applied the correction as roc_019fb641-9666-7f57-966e-dc7f71c0bc84, returned three credits, classified it as released_by_data_correction, and linked ledger entry cms8e8zyb000004jtchz2cbzt. Delivery finalization did not complete, so the lesson remains Completed and the Delivery correction remains pending.

The operator used Delivery's documented pending-finalization retry. Revenue returned correction_id was already used with a different payload. No second financial adjustment or Delivery finalization occurred.

Root cause

The durable applied Revenue row predates ADR-0042. Its request hash covers the ADR-0038 outcome payload without correction_kind or lesson-detail fields. After ADR-0042, Revenue normalizes an outcome request with correction_kind: outcome plus null original_lesson_type_id, proposed_lesson_type_id, original_duration_minutes, and proposed_duration_minutes. Those additive defaults change the request hash even though every ADR-0038 semantic field is identical.

This violates the accepted ADR-0042 compatibility rule that existing callers omitting correction_kind continue as outcome corrections, and the correction API v1.0.0 requirement that an idempotent replay returns the existing durable result. Delivery is restoring its client serializer so outcome calls omit every charge-only field. Revenue still needs legacy semantic replay because its current normalization adds the defaults before hashing.

Asks

Revenue, please:

  1. Make replay lookup for an existing outcome correction compare the legacy ADR-0038 semantic fields, treating omitted correction_kind as outcome and ignoring charge-only null defaults.
  2. Preserve strict mismatch rejection when any real semantic field differs.
  3. Add conformance coverage for a pre-ADR-0042 applied outcome correction replayed after ADR-0042 deployment.
  4. Deploy the repair, replay this correction without posting another ledger entry, and reply with the durable existing response and deployment reference.

After Revenue confirms the compatible replay, Delivery will retry the same correction id, finalize the lesson to Canceled with reason Coach Canceled, verify the Delivery audit and lesson.outcome.corrected event, and confirm that Revenue still has exactly one correction and one linked ledger adjustment.

References

  • adrs/ADR-0038-guarded-lesson-outcome-corrections.md
  • adrs/ADR-0042-guarded-completed-lesson-charge-corrections.md
  • contracts/credit-reservation-lock/lesson-outcome-correction-api-proposal.md
  • memos/2026/2026-07-30-revenue-lesson-outcome-correction-api-production-ready.md
  • memos/2026/2026-08-02-revenue-completed-lesson-charge-correction-api.md

Thread (11 memos)

Aug 2deliveryDelivery acknowledges ADR-0042 and publishes guarded lesson type correction UIAug 2deliveryDelivery legacy outcome replay finalized without a duplicate adjustmentAug 2deliveryDelivery lesson charge apply authentication repaired and Jenny correction finalizedAug 2financeFinance acknowledges ADR-0042 append-only adjustment and correction-period recognition treatmentAug 2platformPlatform acknowledges ADR-0042, publishes lesson.details.corrected v1, and confirms exact Delivery scopesAug 2revenueRevenue proposes guarded completed lesson charge corrections and requests Delivery UI integrationAug 2revenueDelivery lesson charge apply reaches Revenue without authentication or idempotencyAug 2revenueRevenue legacy outcome replay compatibility is liveAug 2revenueRevenue proposes removing negative balance as a lesson correction blockerAug 9platformPlatform acknowledges ADR-0043 and confirms no authorization or event change

View source on GitHub