feat(r5.3): écrans IA — assistant web, corpus administrable, suggestions OT/mobile

- Contrat (76 opérations) : Document expose inCorpus/indexedAt/chunkCount,
  PATCH /documents/{id}/corpus (ASSETS.edit), POST /assistant/reindex
  (bilan chiffré) ; ci-contract vérifie désormais aussi le client mobile.
- Web : page /assistant (chat sourcé — extraits exacts cités, Ouvrir vers
  PDF authentifié ou fiche OT, avertissement permanent ; refus honnête
  chiffré avec action utile) ; Bibliothèque = corpus (bandeau 09-08,
  statut d'indexation par document, interrupteur d'exclusion PDF,
  Réindexer tout) ; fiche OT : « Décrire pour suggérer » (Appliquer =
  geste humain, liseré « suggéré » retiré au choix manuel).
- Mobile : chips de suggestion dans la clôture (un appui = un champ
  pré-rempli, « réseau requis » hors-ligne — la file R4 n'en dépend pas).
- apps/ai : seuils AI_SEUIL_* configurables par env (CI + calibrage).
- CI e2e : service siop2-ai (embeddeur déterministe, seuils calibrés sur
  mesures : match 0,66 vs bruit 0,11) + parcours R5 Playwright (PDF généré
  xref valide → réindexation → réponse sourcée → refus → suggestion).
- Vérifié : 16/16 Playwright, 78 tests API, 23 pytest, 17 jest-expo ;
  chaîne réelle au vrai modèle ONNX (web 7/7, mobile Expo web 6/6).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
pr-daaif
2026-07-17 17:26:22 +01:00
parent 45ae491827
commit 28eecc1fb9
31 changed files with 1431 additions and 24 deletions

View File

@@ -1096,6 +1096,56 @@
}
}
},
"/documents/{id}/corpus": {
"patch": {
"operationId": "updateDocumentCorpus",
"summary": "Inclure/exclure du corpus IA (D3 — réversible, effectif à la prochaine réindexation)",
"tags": [
"documents"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"security": [
{
"bearerAuth": []
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DocumentCorpusUpdate"
}
}
}
},
"responses": {
"200": {
"description": "Document mis à jour",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Document"
}
}
}
},
"404": {
"description": "Inconnu"
}
}
}
},
"/documents/{id}": {
"delete": {
"operationId": "deleteDocument",
@@ -1243,6 +1293,35 @@
}
}
},
"/assistant/reindex": {
"post": {
"operationId": "reindexAssistant",
"summary": "Réindexer le corpus (bibliothèque PDF + bilans clôturés, anonymisés à lingestion — D4)",
"tags": [
"assistant"
],
"security": [
{
"bearerAuth": []
}
],
"responses": {
"200": {
"description": "Bilan dindexation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReindexResult"
}
}
}
},
"503": {
"description": "Service IA indisponible"
}
}
}
},
"/search": {
"get": {
"operationId": "globalSearch",
@@ -4807,6 +4886,26 @@
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"inCorpus": {
"type": "boolean"
},
"indexedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
]
},
"chunkCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
@@ -4818,7 +4917,10 @@
"assetReference",
"workOrderReference",
"uploadedByName",
"createdAt"
"createdAt",
"inCorpus",
"indexedAt",
"chunkCount"
],
"additionalProperties": false
}
@@ -4892,6 +4994,26 @@
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
"inCorpus": {
"type": "boolean"
},
"indexedAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
},
{
"type": "null"
}
]
},
"chunkCount": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
@@ -4903,7 +5025,23 @@
"assetReference",
"workOrderReference",
"uploadedByName",
"createdAt"
"createdAt",
"inCorpus",
"indexedAt",
"chunkCount"
],
"additionalProperties": false
},
"DocumentCorpusUpdate": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"inCorpus": {
"type": "boolean"
}
},
"required": [
"inCorpus"
],
"additionalProperties": false
},
@@ -5256,6 +5394,39 @@
],
"additionalProperties": false
},
"ReindexResult": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"documentsIndexed": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"documentsSkipped": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"reportsIndexed": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"chunks": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
}
},
"required": [
"documentsIndexed",
"documentsSkipped",
"reportsIndexed",
"chunks"
],
"additionalProperties": false
},
"SearchResponse": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",