Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.kaireonai.com/llms.txt

Use this file to discover all available pages before exploring further.

API surface

EndpointPurposeWired scaffold
POST /api/v1/scenarios/runSingle scenario; returns ScenarioResult + 95 % CI on value delta.lib/scenario/shadow-score.ts
POST /api/v1/scenarios/compare2–10 scenarios; ranks by value delta with paired-bootstrap p-values.lib/scenario/multi-compare.ts
POST /api/v1/scenarios/distributionPer-segment offer-share + Gini + KL (W11).lib/scenario/distribution-simulator.ts
POST /api/v1/scenarios/value-finderPareto sweep over revenue × fairness × coverage (W11).lib/scenario/value-finder.ts
POST /api/v1/scenarios/seasonalityDecompose a time-series window into weekly seasonality + trend + residual; optional forward forecast.lib/scenario/seasonality.ts
All three are tenant-scoped, rate-limited (10/min for run, 5/min for compare, 20/min for seasonality), and write AuditLog rows so DSAR exports can cite what was simulated.

Run body shape

{
  "from": "2026-04-01T00:00:00Z",
  "to": "2026-04-28T00:00:00Z",
  "scenario": {
    "offerScoreMultiplier": { "OFFER_PREMIUM_CARD": 1.1 },
    "offerScoreAdd": {},
    "minScore": 0
  },
  "maxTraces": 5000,
  "seed": 42,
  "offerValues": { "OFFER_PREMIUM_CARD": 1500 }
}
  • offerValues is optional. When absent, valueDelta is computed using score as a proxy for value, and the response sets meta.valuesUsedProxy: true.
  • maxTraces caps the archive window at 1–20000 rows.
  • seed controls the bootstrap PRNG so the CI is reproducible.

Compare body shape

{
  "from": "2026-04-01T00:00:00Z",
  "to": "2026-04-28T00:00:00Z",
  "scenarios": [
    { "name": "baseline_plus_5pct", "config": { "offerScoreMultiplier": { "OFFER_X": 1.05 } } },
    { "name": "diversity_boost",    "config": { "offerScoreAdd":        { "OFFER_X": 0.1 } } }
  ]
}
Returns a per-scenario ScenarioResult plus a pValues matrix and a rank ordering by value delta.

Seasonality body shape

{
  "history": [
    { "day": "2026-03-01", "value": 1234 },
    { "day": "2026-03-02", "value": 1190 }
  ],
  "forecast": {
    "startDay": "2026-04-29",
    "days": 14,
    "baseLevel": 1200,
    "upliftFactor": 1.08
  }
}
history requires 7+ points. forecast is optional — when omitted, only the decomposition is returned.

UI

/studio/scenarios ships 5 tabs (W11): Run, Compare, Distribution, Value Finder, Seasonality. Run is the polished single-scenario form with bootstrap-CI on value delta. The other four tabs surface raw JSON request/response panels — operators paste in the body shape, hit Run, see the structured response. Chart wrappers are roadmap polish.

Distribution Simulator (W11)

POST /api/v1/scenarios/distribution slices archived decisions by a segment dimension and emits per-segment offer-share, share-delta, Gini concentration index (0=uniform, 1=winner-take-all), and KL-divergence (baseline ‖ scenario, nats).
{
  "from": "2026-04-01T00:00:00Z",
  "to": "2026-04-28T00:00:00Z",
  "scenario": { "offerScoreMultiplier": { "OFFER_A": 1.2 } },
  "segmentDimension": "tier",
  "segmentResolver": {
    "CUSTOMER_1": { "tier": "gold", "region": "us-east" },
    "CUSTOMER_2": { "tier": "silver", "region": "us-west" }
  }
}
The segmentResolver is operator-supplied because there is no Customer Prisma model — segment data lives in DataSchema-driven ds_* tables and the operator’s UI / batch driver knows how to hydrate it. Customers missing from the resolver are skipped honestly; the meta.tracesScanned + meta.segmentsCovered block reports coverage so operators see what fraction of the window was attributable.

Value Finder (W11)

POST /api/v1/scenarios/value-finder — Pareto-front sweep over revenue × fairness × coverage.
{
  "from": "2026-04-01T00:00:00Z",
  "to": "2026-04-28T00:00:00Z",
  "scenarios": [
    { "name": "baseline", "config": {} },
    { "name": "boost-A",  "config": { "offerScoreMultiplier": { "OFFER_A": 1.2 } } },
    { "name": "boost-B",  "config": { "offerScoreMultiplier": { "OFFER_B": 1.2 } } }
  ],
  "segmentDimension": "tier",
  "offerValues": { "OFFER_A": 100, "OFFER_B": 80 }
}
Response rows[] carries per-scenario revenue / fairness / coverage / picks / dominated. paretoFront[] lists non-dominated names. The recommended field is the Pareto-front member with the highest geometric mean of normalized axes — a conservative default, never binding. Honest limits: fairness is NaN when the archive lacks segments (returned, not silenced). revenue falls back to score-as-proxy when offerValues are absent.

Honest limits

  • Per-offer business value (margin / expected revenue) is best supplied by the caller. When missing, the route falls back to score as a proxy and explicitly flags it in meta.valuesUsedProxy.
  • The compare endpoint loads the archive once per call; very wide windows (maxTraces near the cap) on slow Postgres can take 10+s.
  • The seasonality endpoint does not query the DB for time-series data — the canonical KPI source varies per tenant. Caller supplies the history.