> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solya.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Consommation par l'app

> Comment l'app Next.js lit les vecteurs de décision et d'action via Postgres — services, heatmap d'urgence, workflows pilotés par score, matérialisation de tâches, filtrage par confiance, et lignage immuable par article.

La data platform écrit `gold.decision_vector` et `gold.action_vector`, les réplique vers
Lakebase Postgres, et l'app Solya les y lit. Cette page couvre le **côté app** : comment ces
vecteurs sont lus, filtrés, affichés, attribués et transformés en action.

```mermaid theme={null}
flowchart TD
  LB[(gold_lakebase<br/>decision_vector · action_vector)]
  subgraph App["App Solya (schéma analytics en lecture seule)"]
    SVC["services<br/>decisionVectors · actionVectors · decisionDistribution"]
    HEAT["Heatmap & chips d'urgence<br/>URGENCY_THRESHOLDS"]
    WF["Workflows<br/>scoreDriven / recommended · CREATE_TASKS"]
    PRE["Pré-remplissage espace alertes<br/>+ reco de référence en revue de plan"]
    ITEM["Articles de plan<br/>decision_vector_snapshot (immuable)"]
    BADGE["LineageBadge<br/>recommandé vs final"]
    AUDIT["Journal d'activité<br/>attribution decisionVectorId"]
  end

  LB --> SVC
  SVC --> HEAT
  SVC --> WF
  SVC --> PRE
  WF --> ITEM
  PRE --> ITEM
  ITEM --> BADGE
  ITEM --> AUDIT
```

## Chemin de lecture — schéma analytics + services

Les tables gold sont exposées en schémas Drizzle **en lecture seule** sous
`src/server/database/analytics/schema/gold/` (`decision-vector.ts`, `action-vector.ts`), avec
les constantes de colonnes dans `src/constants/datasetColumns/gold/`. Trois services les
encapsulent :

| Service                | Lit                             | Sert à                                                        |
| ---------------------- | ------------------------------- | ------------------------------------------------------------- |
| `decisionVectors`      | scores `decision_vector`        | enrichir les articles d'alerte déclenchés au dernier snapshot |
| `actionVectors`        | recommandations `action_vector` | pré-remplir les articles de plan, matérialiser les tâches     |
| `decisionDistribution` | `decision_vector` agrégé        | stats d'urgence au grain variante / produit / marque          |

La constante `DecisionDomain`, les clés JSONB `scores` et les seuils d'urgence vivent dans
`src/constants/decisionDistribution.ts` — une source de vérité unique partagée par
l'orchestrateur SQL et les helpers d'UI.

## Seuils d'urgence & heatmap

`URGENCY_THRESHOLDS` mappe les scores bruts en drapeaux « action requise », couleurs de chips
et paliers de heatmap :

```ts theme={null}
URGENT:           0.5            // marque un (variante, magasin) comme nécessitant une action
CHIP_WARNING:     0.3
CHIP_ERROR:       0.6
TIER_BREAKPOINTS: [0.2, 0.4, 0.6, 0.8]   // heatmap à 5 bandes
```

`decisionDistribution` les agrège — p. ex. `shopsInRestockZone` compte les magasins avec
`restock_urgency ≥ 0.5`, et le résumé marque surface un `urgentCount` inter-domaines.

## Workflows pilotés par score

Les stratégies `ADD_ITEMS_TO_PLAN` des workflows routent vers la couche décision
(`src/types/workflows.ts`) :

* **`scoreDriven`** (quantité / matching) — le resolver de la data platform lit le vecteur de
  décision pour fixer la quantité ou apparier les magasins de rebalance. Aucun paramètre côté app.
* **`recommended`** (markdown) — remise de la couche décision avec trois bornes
  (`fallbackPercent` 15, `maxDiscountPct` 70, `marginFloorPct` 0).

Voir [Workflows — actions de plan](/fr/developers/workflows/actions) pour la config complète.

### CREATE\_TASKS — matérialiser le vecteur d'action dans la boîte de réception

L'action de workflow `CREATE_TASKS` transforme les lignes `action_vector` en tâches
`PRODUCT_ACTION`, scopées aux paires `(variantId, shopId)` matchées par le déclencheur :

```json theme={null}
{ "actionType": "CREATE_TASKS", "domains": ["restock", "markdown"], "minConfidence": 0.7 }
```

* **`domains`** — un sous-ensemble non vide de `["restock", "rebalance", "markdown"]`.
* **`minConfidence`** — les lignes sous ce seuil sont supprimées ; les lignes à confiance
  **null** (p. ex. restock) sont toujours conservées.

## Filtrage par confiance à la lecture

`getActionVectorsForItemsAction` (palier riche de l'espace alertes, reco de référence en revue
de plan) applique le seuil de confiance global de l'org à la lecture : une ligne dont la
confiance est sous le seuil est renvoyée avec `resolved: false`, pour que l'UI la traite comme
**« pas de recommandation — saisie manuelle »** plutôt que de pré-remplir une valeur peu fiable.

Le hook de revue de plan `usePlanReviewReferenceReco` récupère des lignes `action_vector`
(dédupliquées, plafonnées à 200 paires) uniquement pour les lignes **sans** snapshot stocké —
afin que les écrans de revue affichent une recommandation de référence même pour les lignes
ajoutées manuellement.

## Lignage immuable par article

Quand un article est émis dans un plan depuis une recommandation, le `decisionVectorSnapshot`
de la stratégie est **capturé à l'émission et stocké de façon immuable** sur l'article de plan
(`*_plan_items.decision_vector_snapshot`, plus `applied_rules`). La forme est
`PlanItemDecisionVectorSnapshot` (`src/types/planItemLineage.ts`) : `capturedAt`, `strategyId` /
`strategyVersion`, `confidence`, `markdownScore` / `agedStockFlag` (markdown), et un fallback
`snapshot_date`. Elle est en `.passthrough()` pour la compatibilité ascendante.

<Warning>
  Le snapshot est **immuable** — il enregistre la décision *originale* de la stratégie. Les
  éditions ultérieures de quantité / remise ne doivent jamais l'écraser. Les articles ajoutés
  manuellement portent un snapshot NULL.
</Warning>

### LineageBadge — recommandé vs final

`LineageBadge` (`src/components/shared/chips/LineageBadge.tsx`) surface l'écart entre ce que la
stratégie a recommandé et ce qui a finalement été persisté (après contraintes OTB / budget /
fournisseur). Il n'affiche rien quand il n'y a ni recommandation ni règle appliquée, ou quand
la recommandation égale la valeur finale sans delta de contrainte — sinon il montre la valeur
recommandée avec une infobulle des règles appliquées et l'id de stratégie.

## Attribution d'audit

Chaque article recommandé est attribué dans le
[journal d'activité](/fr/inventory-plans/lifecycle#journal-d-activité--trail-d-audit) du plan. Une
attribution `DECISION_VECTOR` porte un `decisionVectorId` renvoyant au snapshot ; `MANUAL` et
`WORKFLOW_FALLBACK` ne portent aucune référence de snapshot (`src/constants/planAuditLog.ts`).

## Source (app)

* Schéma analytics : `src/server/database/analytics/schema/gold/{decision-vector.ts, action-vector.ts}`
* Services : `src/server/services/{decisionVectors, actionVectors, decisionDistribution}/`
* Constantes : `src/constants/decisionDistribution.ts`, `src/constants/taskConfidence.ts`, `src/constants/planAuditLog.ts`
* Lignage : `src/types/planItemLineage.ts`, `src/components/shared/chips/LineageBadge.tsx`
* Workflows : `src/types/workflows.ts`
