Skip to main content
gold.decision_context is the foundation of the decision layer. It materializes one row per (organization_id, variant_id, shop_id, snapshot_date), consolidating stock state, margin, forecast, and dimension keys into a single shape that every decision-vector scorer reads. Build it once, score it three ways.

Lineage — three gold inputs

The builder anchors on gold.stock_snapshot (one position = one stock row) and LEFT-joins margin and forecast onto it, collapsing every input across size_taxonomy_id first.
  • stock_snapshot is the anchor: no positions → nothing to build (skip_task_if_empty).
  • sales_kpis supplies gross_margin_pct (LEFT JOIN on the position key).
  • sales_forecasts is best-effort — filtered to granularity = 'daily', summed over the next-30-day window; a missing forecast leaves the column NULL.

Column reference

Audit columns (created_at, updated_at) are omitted. The aged_stock_flag is the only non-position column that is NOT NULL.

Stock state

Sales & margin

Forecast

Dimension keys (for rule-scope matching)

v1 always-NULL slots

Seven columns are typed and reserved but always NULL in v1target_stock, lead_time_days, sell_through_7d/30d/90d, category_id, supplier_id. Their type and nullability are stable so the writer can fill them later without a DDL migration.
Because target_stock is always NULL in v1, the rebalance surplus/deficit ratios collapse to 0 across the catalogue (a position with no target genuinely cannot be classified as surplus or deficit). This is correct, deterministic behavior — real rebalance scores land the day target_stock is populated. See the decision vector page.
The scoring layer treats NULL as “skip this signal for this position” by coalescing each NULL input to a neutral default before the math runs (documented per-domain on the next page).

Validation

Rules are embedded on the schema and applied by the writer:
  • Errors (fail the task): decision_context_not_empty, decision_context_required_fields (organization_id, snapshot_date, aged_stock_flag non-NULL), decision_context_pk_unique.
  • Warnings: non-negativity checks on current_stock, days_of_cover, forecast_30d.
A DecisionContextHealthTask raises [freshness] (no recent snapshot) or [row-count-drift] (today’s slice diverges from yesterday’s) breaches for on-call triage.

Source

  • Schema: pipelines/shared/schemas/gold/decision_context.py
  • Writer: pipelines/layers/gold/tasks/build_decision_context/task.py
  • Repo doc: docs/gold/decision-context.md