Skip to main content

ADR-0202: Navin Enterprise Price and Promotion Optimisation Agent, retail product layer above the Control Plane

  • Status: proposed (2026-11-05)
  • Deciders: Navin Enterprise AI platform team, mission UC-13 (agent_uses_cases/13_Retail_Optimisation_Prix_Promotions.md)
  • References: ADR-0176 (generic module pattern), ADR-0180 (shared frontend shell), ADR-0174 (memory provider), ADR-0191 (supply chain model product), OPA package eai.retail_prix (deploy/policies/opa/retail_prix.rego), OpenFGA fragment deploy/policies/openfga/products/retail-prix-promotions.fga, Manager template navin-retail-prix-promotions-agent (published: false).

Context​

A retailer wants to consolidate prices, costs, sales, stock and authorised competitor observations to prepare explainable prices and promotions that comply with validated rules and are published after approval. The brief requires eight modules (§7: price-foundations, competitive-observations, pricing-analytics, promotion-designs, pricing-scenarios, price-reviews, price-publications, promotion-evaluations), a server side state machine (data_ready to evaluated) and six numeric acceptance scenarios (margin 20 and markup rate 22.222 % after a 10 % discount, floor 15 blocking a scenario at 10, non stackable promotion with a coupon, different pack size, partial publication on three channels, cost changed after approval).

The platform provides identity, OpenFGA, OPA, approvals, durable jobs, the document pipeline, RAG, memory and observability. No real PIM, ERP, POS, pricing engine or competitor source is connected in the repository: connectors are exercised on a deterministic sandbox declared sandbox.

Decision​

  1. Standalone product navin-enterprise-retail-prix-promotions/, Python package navin_prix, PostgreSQL schema prix with RLS on every tenant table, outbox and immutable audit; API /api/v1/retail-prix-promotions on port 8485, Redis 6406, UI 3486 served by the shared shell (no own frontend code).
  2. The engine computes, the LLM explains: margins, markup rates, discount stacking and rule checks are deterministic, Decimal per currency, with engine_version, ruleset_version and a frozen input. Price rules (floors, ceilings, minimum margin, price endings, families, legal constraints quoted from their source) are versioned data with their reference; no regulation is invented.
  3. Elasticity and uplift are statistical estimates with an interval and a data window, never certainties nor causal claims; cannibalisation and halo are flagged as estimates.
  4. No effective price or promotion change without human approval (maker-checker: the requester never approves their own request, neither the copilot nor a robot approves) and confirmation by the pricing system or the ERP/POS. Publication is a side_effect action of the Action Gateway with Idempotency-Key, If-Match on the price version, effective dates and a rollback proposal; an uncertain answer becomes unknown_pending_confirmation and the source is re-read before any retry.
  5. Competitor prices: authorised sources only, with provenance and observation date; no collection outside these sources, no coordination with competitors.
  6. Manager template prepared and not published; publication after explicit validation.

Consequences​

  • A failing channel leaves the campaign published_partial with a targeted reconciliation.
  • A cost changed after approval invalidates the approval according to the configured rule.
  • Real connectors remain to be connected; the sandbox is not a validated integration.