# Guide de l'espace Kortex : le référentiel et le fonctionnement du dashboard

Ce guide explique ce que contient un espace Kortex, à quoi sert chaque
élément et comment les agents IA s'en servent. Il s'adresse à l'équipe du
site comme à une IA qui pilote l'espace par l'[API](/modules/dashboard-api/).

Il décrit le fonctionnement, jamais vos données.

## L'espace en bref

Chaque site suivi par Kortex a son espace, à l'adresse
`<site>.kortex.center`. Il réunit deux composants :

- le **dashboard**, ce que vous voyez : le référentiel du site, les
  articles, le suivi des actions et, selon les modules, les ventes ;
- le **superviseur**, les agents IA : ils lisent le référentiel, rédigent,
  vérifient le site et proposent des corrections.

**Règle de fond : les agents proposent, l'équipe du site décide.** Un article
n'est mis en ligne qu'après une décision humaine (ou d'un script muni d'une
clé `destructif`), et une action n'est jamais « cochée » à la main : son état
se déduit de constats.

| Écran de l'espace | Ce qu'il montre | Section du guide |
|---|---|---|
| Connaissance › Référentiel | les lignes du référentiel | [Le référentiel](#le-referentiel) |
| Connaissance › Coller depuis un tableur | l'import par collage | [Remplir le référentiel](#remplir-le-referentiel) |
| Contenus › Ce que le modèle lit | le texte exact remis aux agents | [Ce que le modèle lit](#ce-que-le-modele-lit) |
| Connaissance › Documents historiques | les anciens documents « faits » et « charte » | [Documents historiques](#documents-historiques) |
| Connaissance › Prompts des agents | les consignes par tâche | [Les prompts des agents](#les-prompts-des-agents) |
| Contenus › Stock d'idées, Générer un lot | les sujets à écrire et leur planning | [Le stock d'idées](#le-stock-d-idees) |
| Contenus › Articles, Demander un article | les articles et leurs décisions | [Les articles et les décisions](#les-articles-et-les-decisions) |
| Suivi des actions › … | le plan d'actions et ses preuves | [Le suivi des actions](#le-suivi-des-actions) |
| Réglages › Publication | comment les décisions arrivent sur le site | [La publication sur le site](#la-publication-sur-le-site) |

## Le référentiel

Le référentiel est **la seule source de vérité que les agents ont le droit
d'utiliser** sur votre marque et vos produits. Un rédacteur n'affirme rien
qui n'y figure pas. Une allégation absente du référentiel est une allégation
que l'agent ne fera pas.

### Une ligne du référentiel

Le référentiel est une liste de lignes. Chaque ligne porte :

| Champ | Sens | Exemple |
|---|---|---|
| `type` | la famille de la ligne (voir ci-dessous) | `FAIT` |
| `groupe` | l'entité à laquelle elle se rattache | `marque` |
| `cle` | la propriété décrite | `fabrication` |
| `valeur` | ce qui est vrai | `Fabriqué en France` |
| `preuve` | comment on le prouve : une URL, une source | `https://…/certificat.pdf` |
| `directive` | oui : la ligne est une **consigne** au modèle, pas une donnée | non |
| `consigne_redacteur` | une précision destinée au rédacteur, reprise telle quelle | « Toujours citer l'atelier » |

Le trio (`type`, `groupe`, `cle`) est unique : réécrire une ligne avec le
même trio la met à jour au lieu d'en créer une seconde.

### Les types de lignes

Le vocabulaire est ouvert, mais les agents reconnaissent ces types :

| Type | À quoi il sert |
|---|---|
| `FAIT` | Un fait citable sur la marque, l'entreprise, un engagement. Le groupe `marque` (clés `nom`, `site`, `baseline`, `fabrication`) donne le nom de marque employé dans les textes. C'est le type par défaut d'un import. |
| `PRODUIT` | Ce que l'on sait d'un produit : nom, composition, usage. |
| `DOCTRINE` | Une règle éditoriale : ton, manière de parler des produits. |
| `ALLEGATION` | Une allégation encadrée et la condition qui la permet (« employable si certifié »). |
| `INTERDIT` | Un terme que les textes ne doivent pas employer. La garde d'écriture et la vérification des pages s'en servent. |
| `EXCEPTION` | Une phrase autorisée malgré un terme interdit, parce que le contexte protège la marque. |
| `CADRE_JURIDIQUE` | Le fondement juridique d'un interdit ou d'une allégation. |
| `REFORMULATION` | Une reformulation déjà approuvée, que les agents réemploient. |
| `CATEGORIE` | Une catégorie du site (un « silo »), avec son identifiant WordPress. |
| `AUTEUR` | Un auteur du site (une persona), avec son identifiant WordPress. |
| `COCON` | Un cocon sémantique : il relie un silo, un auteur et des articles. |

`CATEGORIE`, `AUTEUR` et `COCON` décrivent la structure du site. Le
superviseur refuse de démarrer la rédaction tant qu'elle est incomplète :
il ne classerait pas un article au hasard.

### Ce que le modèle lit

Les agents ne lisent pas la grille : ils lisent un **texte** construit à
partir d'elle (écran « Ce que le modèle lit », API
`GET /api/seo/references-v2/rendu`). L'écran l'affiche mis en forme ; le
bouton **Markdown** montre le texte exact que reçoit le modèle.

- Une section par entité (`## TYPE — groupe`), dans l'ordre des lignes.
- Les **directives** d'abord, en citations, puis un tableau
  clé / valeur / preuve / consigne.
- Le superviseur range `DOCTRINE`, `INTERDIT`, `ALLEGATION`,
  `CADRE_JURIDIQUE` et tout type inconnu dans la **charte de marque**, et le
  reste dans le **référentiel de faits**.
- Un référentiel vide répond `404 referentiel_vide` : un document vide
  n'interdirait rien, l'agent ne doit pas le prendre pour une autorisation.

Quand le rédacteur manque d'un fait, il le signale au lieu de l'inventer.
Ces manques sont regroupés (`GET /api/seo/faits-manquants`) : c'est la liste
de ce qu'il faut ajouter au référentiel.

### Remplir le référentiel

Trois façons, du plus simple au plus automatisable :

1. **À l'écran** (Connaissance › Référentiel) : ajouter, corriger ou
   supprimer une ligne.
2. **Coller depuis un tableur** : copiez un tableau avec une ligne
   d'en-tête (`type`, `groupe`, `cle`, `valeur`, `preuve`, `directive`).
   L'aperçu montre ce qui sera ajouté, modifié ou laissé ; l'import est
   « tout ou rien » et **ne supprime jamais** une ligne absente du collage.
   `directive` vaut oui pour `1`, `oui`, `vrai`, `true` ou `x`.
3. **Par l'API** (clé `pilotage`) :

| Geste | Route |
|---|---|
| Lire la grille et le texte rendu | `GET /api/seo/references-v2` |
| Lire des lignes par type | `GET /api/seo/references-v2/lignes?type=FAIT,PRODUIT` |
| Prévisualiser un collage (rien n'est écrit) | `POST /api/seo/references-v2/apercu` (texte tabulé) |
| Importer un collage | `POST /api/seo/references-v2/importer` (texte tabulé) |
| Ajouter ou mettre à jour une ligne | `POST /api/seo/references-v2/ligne` `{type, groupe, cle, valeur, preuve, directive}` |
| Ajouter un lot de faits sans rien écraser | `POST /api/seo/references-v2/lignes/lot` `{type, lignes: [{groupe, cle, valeur, preuve}]}` (preuve en `http(s)://`, 1 000 lignes au plus) |
| Corriger une ligne | `PUT /api/seo/references-v2/lignes/:id` |
| Supprimer une ligne (définitif, clé `destructif`) | `DELETE /api/seo/references-v2/lignes/:id` |

**Bonnes pratiques.** Une ligne = une affirmation. Mettez toujours une
preuve : c'est elle qui permet de défendre un texte. Laissez vide ce que vous
ne pouvez pas prouver : l'absence est une garde, pas un oubli.

### Documents historiques

Avant le référentiel en lignes, la doctrine tenait dans deux documents :
**faits** (Markdown) et **charte de marque** (YAML, dont les commentaires
faisaient partie de la règle). Ils restent consultables, avec leurs versions
(`GET /api/seo/references`, `GET /api/seo/references/:nom`,
`…/historique`). Les agents lisent désormais le référentiel en lignes.

## Les prompts des agents

Un prompt est la consigne remise au modèle pour **une tâche sur un type de
contenu** : le couple (verbe, type). Il y en a **33 qui ont un sens** ; la doc
de chacun — ce que l'agent reçoit du référentiel et du contexte, ce qu'il
rend, l'interface et l'API — est sur
[kortex.center/modules/prompts](https://kortex.center/modules/prompts/).

- Verbes : `rediger` (écrire), `regenerate` (réécrire), `reformulate`
  (reformuler un passage), `repondre`, `generer_lot` (lot d'idées).
- Types : article, fiche produit, méta-description, texte alternatif, chapô,
  H1, fragment d'article ou de produit, questions-réponses d'article ou de
  produit, lot d'idées.
- Les combinaisons sans objet (rédiger un fragment seul, reformuler un
  article entier…) sont refusées (`400 couple_sans_objet`), avec le couple à
  utiliser à la place.
- Les prompts de **produit** (fiche, fragment, questions-réponses de produit)
  n'existent que si le site a le module **E-commerce** (`400 module_requis`
  sinon).

**Ce que les agents en font aujourd'hui.** Ils lisent le prompt de l'espace
pour **rédiger un article**, **réécrire un article ou une fiche produit** et
**reformuler un fragment** ; pour les autres couples, ils suivent encore leur
consigne interne (chaque page de la doc le dit). Votre prompt remplace la
consigne **éditoriale** — ton, angle, ce qu'il faut mettre en avant ; Kortex
garde toujours à la suite les gardes (aucun chiffre inventé, conformité), la
demande de l'équipe citée mot pour mot, le format de sortie et le
référentiel. Un prompt ne peut donc ni casser un article, ni lever une garde.

Chaque enregistrement crée une **version inactive**. Seule l'activation
d'une version change ce que reçoit le modèle ; une seule version est active
par couple. Sans version active, l'espace répond `404 prompt_absent` et
l'agent garde sa consigne interne. Les placeholders déclarés doivent
apparaître dans le texte. Réservé aux administrateurs.

## Le stock d'idées

Le stock d'idées est le **plan éditorial** : des sujets prêts à écrire,
rédigés sous forme de brief.

| Champ du brief | Sens |
|---|---|
| `sujet` | le sujet de l'article (requis) |
| `slug` | la future adresse, unique (requis) |
| `requete_cible` | la recherche que l'article doit capter (requis) |
| `intention` | `informationnelle`, `comparative` ou `transactionnelle` (requis) |
| `cocon` | le cocon de rattachement (requis) |
| `mot_cle_principal`, `mots_cles_secondaires` | les mots-clés |
| `titre_h1_suggere` | le titre proposé, 70 caractères au plus |
| `structure_h2` | le plan : une liste de questions |
| `cta` | l'appel à l'action |
| `notes` | tout ce que le rédacteur doit savoir |

Chaque idée a une **priorité** (plus petit = plus tôt) et un statut :
`stock`, `redaction_demandee`, `publiee` ou `abandonnee`.

**Le dépilement** envoie les idées en rédaction selon un planning : jours de
production, nombre d'articles par jour, heure (heure de Paris). Il est
**éteint** sur un espace neuf. Une fois allumé, il vérifie chaque heure s'il
est dû, prend les idées les plus prioritaires et demande leur rédaction. On
peut aussi dépiler à la main, une idée ou plusieurs.

Le planning se règle en haut de **Contenus › Stock d'idées** (administrateur) :
cases des jours, idées par jour (1 à 20), heure, et « Dépiler
automatiquement ». Sous le réglage, l'écran dit le prochain départ prévu et la
date du dernier dépilement automatique. Exemple par l'API, lundi, mercredi et
vendredi, une idée à 6 h :

```json
PUT /api/seo/planning-depilement
{ "jours_production": [1, 3, 5], "nb_par_jour": 1, "heure_depilement_locale": "06:00", "actif": true }
```

Les jours vont de 1 (lundi) à 7 (dimanche) ; chaque champ est facultatif.

Routes (administrateur) : `GET/POST /api/seo/idees`, `PUT /api/seo/idees/:id`,
`PUT /api/seo/idees/:id/priorite`, `POST /api/seo/idees/depiler-maintenant`,
`GET/PUT /api/seo/planning-depilement`.

## Les articles et les décisions

Un article naît d'un brief (Demander un article, ou le dépilement). L'agent
le rédige, puis **l'espace attend une décision**. Chaque décision est un
ordre donné aux agents, qu'un agent prend en charge puis exécute.

| Décision | Ce qu'elle fait | Clé requise |
|---|---|---|
| `approve` | « Ce texte est bon » : l'agent dépose un brouillon sur le site | `pilotage` |
| `reject` | refuse le texte, avec un motif d'au moins 10 caractères | `pilotage` |
| `reply` | ajoute un message à l'échange | `pilotage` |
| `regenerate` | fait réécrire, avec des consignes | `pilotage` |
| `publish` | met en ligne le brouillon approuvé | `destructif` |
| `depublier` | retire un article publié | `destructif` |
| `decrire_media` | donne le texte alternatif d'une image | `pilotage` |
| `classer` | choisit catégories et étiquettes | `pilotage` |
| `resumer` | écrit l'extrait | `pilotage` |
| `replanifier` | change la date de publication | `pilotage` |
| `renommer_adresse` | change l'adresse (l'ancienne n'est pas redirigée) | `pilotage` |

Une seule décision « agissante » (`approve`, `regenerate`, `publish`,
`depublier`) à la fois par article : les autres attendent qu'elle aboutisse.

Route : `POST /api/seo/decisions/:verbe` avec
`{entity_type: "content", entity_id}`. Lecture : `GET /api/seo/decisions`,
`GET /api/seo/content`, `GET /api/seo/content/:id`.

## Le suivi des actions

Le suivi des actions répond à une question : **ce qui devait être fait sur
le site l'est-il vraiment, et le reste-t-il ?** Personne ne coche de case.

- Une **action** est un engagement du plan : un titre, une échéance, un
  responsable, une cible, et l'épreuve qui dira si c'est fait.
- Une **observation** est un constat daté : une mesure, une lecture par IA
  ou une déclaration. Elle n'est jamais réécrite.
- L'**état** de l'action se calcule à partir des observations : `fait`,
  `a_faire`, `defait`, `a_arbitrer`, `declaratif` ou `a_revalider`.

Les règles qui comptent :

- seule une **mesure** peut faire passer une action à `defait` ;
- un constat d'IA doit être confirmé, sinon l'action passe à `a_arbitrer` ;
- un **arbitrage** humain tranche, avec un motif, et ne vaut que tant que la
  cible n'a pas changé (sinon : `a_revalider`).

Les autres écrans :

- **Rapports déposés** : un audit (PDF, docx) déposé est lu par un agent,
  qui en tire des actions.
- **Quarantaine** : les lignes d'un plan que l'import n'a pas su rattacher.
- **Abandonnées** : les actions sorties du plan, rétablissables.
- **Correctifs** : les corrections demandées aux agents.

Routes principales : `GET /api/seo/registre`,
`POST /api/seo/registre/actions`, `POST /api/seo/registre/arbitrages`,
`POST /api/seo/registre/:action_id/verifier`,
`POST /api/seo/registre/:action_id/corriger`,
`POST /api/seo/registre/recalcul`.

## La publication sur le site

Vos décisions (approuver, publier, dépublier, renommer l'adresse, changer
l'en-tête) n'ont d'effet que lorsqu'elles arrivent sur le site du client.
**Réglages › Publication** (administrateur) dit comment :

| Connecteur | Qui écrit sur le site | Pour quel site |
|---|---|---|
| WordPress | le superviseur, par l'API REST du site | un WordPress (le réglage de départ) |
| Webhook | l'espace, qui envoie chaque décision, signée, à votre service | un site statique (Astro, Hugo, Eleventy, Jekyll) ou tout site équipé de son propre service |
| Aucun | personne | un site en lecture seule : les agents lisent et rédigent, rien n'est publié |

**Un seul écrivain par site.** Avec le webhook, le superviseur ne reçoit plus
les décisions qui écrivent sur le site ; il continue de lire le site et de
rédiger.

### Mettre en service le webhook

1. Choisir **Webhook**, saisir l'URL de votre service (`https://…`, sans
   paramètre) et le format du texte (**Markdown** pour un site statique) ;
   enregistrer.
2. Coller le **secret partagé** (32 à 256 caractères), le même que celui de
   votre service. Il est chiffré et jamais réaffiché.
3. **Tester la connexion** : « Connexion établie » quand votre service répond.

Les décisions prises avant l'activation ne partent pas. Votre service suit
[le contrat public du connecteur](https://kortex.center/modules/publication-webhook/).

### Suivre les envois

- La **file** (Réglages › Publication) montre chaque envoi : en attente,
  appliqué, refusé, en réessai, en échec. Les envois partent **dans l'ordre**,
  un à la fois ; une publication à date attend sa date.
- Votre service est indisponible : l'espace réessaie après 1 min, 5 min,
  15 min, 1 h et 6 h, puis l'envoi passe **en échec** et bloque les suivants
  (pour qu'un `publier` ne parte jamais avant son `approuver`). Débloquez-le :
  « Réessayer maintenant » ou « Abandonner cet envoi ».
- Votre service refuse (texte trop court, adresse déjà prise…) : le motif
  s'affiche tel quel ; corrigez dans l'espace et décidez à nouveau.
- Sur la fiche d'un article, **Sur le site** dit le dernier envoi et donne
  « Voir le brouillon » ou « Voir la page ».
- **Mettre en pause** : rien ne part, les décisions s'empilent et partent dans
  l'ordre à la reprise.

Routes (administrateur, fermées aux clés API) :
`GET/PUT /api/admin/publication`, `PUT /api/admin/publication/secret`,
`PUT /api/admin/publication/etat`, `POST /api/admin/publication/test`,
`POST /api/admin/publication/envois/:id/reessayer|abandonner` ; état d'un
contenu : `GET /api/seo/publication/contenus/:id`.

## Activer l'API d'un espace

Deux étapes, deux acteurs différents — et c'est voulu : **une clé ne peut
jamais fabriquer une autre clé.**

| Étape | Qui | Avec quoi |
|---|---|---|
| 1. Allumer l'option « API » du site | l'équipe Kortex, ou un script / une IA | la console kortex.center, ou une clé **kortex.center** de portée `pilotage` |
| 2. Créer la clé de l'espace | un **administrateur du site**, connecté | l'espace du site, Réglages › Clés API |
| 3. Utiliser la clé | le script ou l'IA | `Authorization: Bearer kx_…` sur `https://<site>.kortex.center` |

### Étape 1 : allumer l'option API du site

**À la main** : console kortex.center › Sites › fiche du site › Modules,
cocher « API », « Enregistrer les modules ».

**Par l'API de kortex.center** (clé de la plateforme, portée `pilotage`) :

```sh
export KORTEX_API_KEY='kx_…'   # clé de kortex.center, PAS celle d'un espace
K=https://kortex.center

# 1. Trouver l'identifiant du site à partir de son slug
curl -sS -H "Authorization: Bearer $KORTEX_API_KEY" "$K/api/admin/sites" \
  | jq '.sites[] | select(.slug == "acheter-fute") | .site_id'

# 2. Lire ses modules actuels
curl -sS -H "Authorization: Bearer $KORTEX_API_KEY" "$K/api/admin/sites/42" | jq '.modules'

# 3. Les renvoyer TOUS, avec api allumé
curl -sS -X PUT -H "Authorization: Bearer $KORTEX_API_KEY" -H 'content-type: application/json' \
  "$K/api/admin/sites/42/modules" \
  -d "$(curl -sS -H "Authorization: Bearer $KORTEX_API_KEY" "$K/api/admin/sites/42" \
        | jq '{modules: (.modules | .api = {actif: true})}')"
```

- Le corps doit contenir **les cinq modules** (`ecommerce`, `shippingbo`,
  `seo`, `merchant`, `api`) : un corps partiel est refusé
  (`400 modules_invalide`), jamais complété au hasard. D'où l'étape 2 :
  lire, modifier `api`, renvoyer le tout.
- Le réglage part vers l'espace en quelques secondes. Pour vérifier :
  `GET https://<site>.kortex.center/llms.txt` répond `200` quand l'API est
  allumée, `404 module_inactif` tant qu'elle ne l'est pas.
- **Éteindre** : même appel avec `api = {actif: false}`. Toutes les clés de
  l'espace sont refusées à la requête suivante ; elles reviennent si l'on
  rallume (sauf expirées ou révoquées).

### Étape 2 : créer la clé dans l'espace

Seul un **administrateur du site**, connecté à son espace, peut créer une
clé. Ni la clé de kortex.center ni une clé d'espace ne le peuvent :
`/api/cles` répond `403 session_requise` à toute clé.

**Le site n'a pas encore d'administrateur ?** Invitez-le, par email :

- à la déclaration du site, l'email du premier administrateur est
  **obligatoire** : `POST /api/admin/sites {slug, domaine, email}` ;
- ensuite, pour un site existant :
  `POST /api/admin/sites/:id/membres {email, nom?}` (clé kortex.center,
  portée `pilotage`).

Un email inconnu reçoit un lien valable 7 jours pour choisir son mot de
passe ; son compte n'existe qu'après. Un email déjà connu est rattaché tout
de suite, sans lien et sans changer son mot de passe. **Le lien ne sort que
par email**, jamais dans une réponse d'API : une IA invite, mais c'est la
personne invitée qui ouvre son compte. La réponse dit si l'email est parti
(`email_envoye`).

1. Se connecter sur `https://<site>.kortex.center/connexion/`.
2. Réglages › **Clés API** (l'entrée n'apparaît que si l'option API est
   allumée et pour un administrateur).
3. Donner un nom qui dit à quoi sert la clé, choisir la **portée** et la
   **durée** (30, 90 ou 365 jours), créer.
4. **Copier la clé tout de suite** : elle n'est montrée qu'une fois.
5. La confier à l'IA ou au script par un gestionnaire de secrets ou une
   variable d'environnement — jamais dans une URL, un dépôt ou un ticket.

Quelle portée choisir :

| Portée | Pour une IA qui… |
|---|---|
| `lecture` | analyse le référentiel, les articles, le suivi des actions |
| `pilotage` | remplit le référentiel, alimente les idées, demande et fait réécrire des articles, arbitre des actions |
| `destructif` | doit aussi **publier**, dépublier ou supprimer — à réserver à un usage précis |

### Étape 3 : vérifier la clé

```sh
export KORTEX_SITE=https://acheter-fute.kortex.center
export KORTEX_SITE_KEY='kx_…'   # la clé de l'espace
curl -sS -H "Authorization: Bearer $KORTEX_SITE_KEY" "$KORTEX_SITE/api/me"
```

La réponse dit au nom de quel administrateur la clé agit, sa portée et sa
date d'expiration (`"auth": "cle"`). Un `401` signifie : clé fausse,
expirée, révoquée, compte désactivé — ou option API éteinte.

**Une IA à qui l'on demande « active l'API de ce site »** fait l'étape 1
(si elle a une clé kortex.center), invite l'administrateur s'il n'y en a
pas encore, puis **demande** la clé de l'espace à cet administrateur : elle
ne peut pas la créer elle-même.

## Pour une IA qui pilote un espace

Ordre de travail recommandé :

0. Pas encore de clé, ou l'espace répond `404 module_inactif` : voir
   [Activer l'API d'un espace](#activer-l-api-d-un-espace).
1. `GET /api/me` : vérifier la clé, sa portée et son expiration.
2. Lire `GET /api/seo/references-v2/rendu` : c'est exactement ce que lisent
   les rédacteurs. Ne rien affirmer qui n'y figure pas.
3. Combler les manques : `GET /api/seo/faits-manquants`, puis ajouter des
   lignes `FAIT` **avec une preuve** (`POST /api/seo/references-v2/ligne`).
4. Alimenter le stock d'idées avec des briefs complets, puis laisser le
   dépilement ou dépiler à la main.
5. Relire les articles proposés et décider ; ne publier (`publish`) qu'avec
   l'accord de l'équipe du site. Après une décision, suivre son arrivée sur
   le site : `GET /api/seo/publication/contenus/:id` (connecteur webhook ;
   un refus du site porte son motif dans `dernier_message`).
6. Suivre les actions par leurs états ; arbitrer avec un motif clair.

Chaque écriture faite par une clé est inscrite au journal du site, avec le
début de la clé et le compte au nom duquel elle agit.
