From cb7edb0b84ee28c917536a8d981cc5cb7ff36945 Mon Sep 17 00:00:00 2001 From: NuklearRabbit <145918611+NuklearRabbit@users.noreply.github.com> Date: Mon, 10 Aug 2026 21:02:47 +0200 Subject: [PATCH] M31: align RAG verification with provider contract --- PROJECT_STATE.md | 4 +++- backend/app/services/knowledge/ragcore.py | 7 ++++--- backend/tests/test_knowledge.py | 2 +- docs/09-ragcore-integration.md | 4 +++- frontend/e2e/recruiter-polish.spec.ts | 2 +- frontend/src/i18n/locales/en-GB/knowledge.json | 4 ++-- frontend/src/i18n/locales/fr-BE/knowledge.json | 4 ++-- frontend/src/i18n/locales/nl-BE/knowledge.json | 4 ++-- 8 files changed, 18 insertions(+), 13 deletions(-) diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index 58a9431..fde98b8 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -2702,7 +2702,9 @@ evidence yet." - RAGcore health now verifies every language-specific managed source through the documented exact `/v1/documents` identity lookup. Only an active document with a - published active version and the authoritative Fleet Ops content hash is counted. + published active version is counted. RAGcore's provider-owned `content_sha256` hashes + its canonical parsed artifact rather than the raw upload, so it is deliberately not + compared with Fleet Ops's source-file hash. Lookups are bounded, concurrent and cached for five minutes; an unavailable verifier remains explicitly unknown instead of being presented as zero or as a reported count. - Persisted n8n sync provenance no longer downgrades the stronger provider-verified diff --git a/backend/app/services/knowledge/ragcore.py b/backend/app/services/knowledge/ragcore.py index 944bb0b..9ec79b2 100644 --- a/backend/app/services/knowledge/ragcore.py +++ b/backend/app/services/knowledge/ragcore.py @@ -163,7 +163,7 @@ class RAGcoreKnowledgeProvider: else: detail += ( f" {verified_document_count}/{len(documents)} managed sources have " - "an active published version with the expected content hash." + "an exact active published document in the configured space." ) except (httpx.HTTPError, ValueError) as exc: available = False @@ -177,7 +177,9 @@ class RAGcoreKnowledgeProvider: collection=self._settings.ragcore_collection, # RAGcore deliberately has no browse/count endpoint. Fleet Ops instead # verifies each managed source through its exact identity lookup and only - # counts an active published version whose content hash still matches. + # counts an active document with a published active version. RAGcore's + # content_sha256 describes its canonical parsed artifact, not the uploaded + # source bytes, so comparing it with Fleet Ops's source hash would be false. document_count=verified_document_count, source_document_count=len(documents), reported_synced_document_count=None, @@ -224,7 +226,6 @@ class RAGcoreKnowledgeProvider: and item.get("status") == "active" and isinstance(active_version, dict) and active_version.get("status") == "published" - and active_version.get("content_sha256") == document.content_hash ) try: diff --git a/backend/tests/test_knowledge.py b/backend/tests/test_knowledge.py index 1859468..62f6507 100644 --- a/backend/tests/test_knowledge.py +++ b/backend/tests/test_knowledge.py @@ -346,7 +346,7 @@ def test_ragcore_provider_verifies_published_documents_and_caches_count(monkeypa "status": "active", "active_version": { "status": "published", - "content_sha256": document.content_hash, + "content_sha256": "provider-canonical-hash", }, } ] diff --git a/docs/09-ragcore-integration.md b/docs/09-ragcore-integration.md index 09332f6..bfe514b 100644 --- a/docs/09-ragcore-integration.md +++ b/docs/09-ragcore-integration.md @@ -31,7 +31,9 @@ provide an exact identity lookup through `GET /v1/documents?source_id=...&extern Fleet Ops uses that documented read contract concurrently and with bounded per-request timeouts for every managed source in the requested language. A document counts only when RAGcore returns exactly one active document in the configured space with a published active -version whose `content_sha256` matches Fleet Ops's authoritative file. Results are cached +version. RAGcore's `content_sha256` represents its canonical parsed artifact rather than +the uploaded source bytes, so Fleet Ops deliberately does not compare that provider-owned +hash with its raw Markdown hash. Results are cached for five minutes. This produces an independently verified `document_count` without changing RAGcore or relabelling an upload/sync report as index evidence. If exact verification is temporarily unavailable, `document_count` remains `null` and the sync report stays visibly diff --git a/frontend/e2e/recruiter-polish.spec.ts b/frontend/e2e/recruiter-polish.spec.ts index ab02c41..a8daa58 100644 --- a/frontend/e2e/recruiter-polish.spec.ts +++ b/frontend/e2e/recruiter-polish.spec.ts @@ -80,5 +80,5 @@ test("Knowledge Hub renders independently verified RAGcore index evidence", asyn await page.goto("/knowledge"); await expect(page.getByText("11 procedures geïndexeerd")).toBeVisible(); - await expect(page.getByText("actief gepubliceerd en inhoudelijk geverifieerd")).toBeVisible(); + await expect(page.getByText("exact gevonden en actief gepubliceerd")).toBeVisible(); }); diff --git a/frontend/src/i18n/locales/en-GB/knowledge.json b/frontend/src/i18n/locales/en-GB/knowledge.json index 6ea4844..99dadf1 100644 --- a/frontend/src/i18n/locales/en-GB/knowledge.json +++ b/frontend/src/i18n/locales/en-GB/knowledge.json @@ -23,11 +23,11 @@ "checkout-procedure": "Required checkout controls" }, "statistics": { - "verifiedIndexed": "actively published and content-verified", + "verifiedIndexed": "exactly matched and actively published", "sourceDocuments": "source documents in this language", "reportedSynced": "sync reported by n8n", "reportedFailed": "sync failures reported", - "lastSync": "Latest sync report: {{when}}. Index state is independently checked against each managed source's active RAGcore version and content hash.", + "lastSync": "Latest sync report: {{when}}. Index state is independently checked through each managed source's exact identity and active RAGcore version.", "noSyncReport": "No sync report has been received yet. Index evidence is checked separately through active RAGcore versions." }, "providerNote": "This demo answers from a small, fixed set of indexed procedures — not a live RAGcore connection. A live RAGcore backend will later take over the same interface without changing how this page works.", diff --git a/frontend/src/i18n/locales/fr-BE/knowledge.json b/frontend/src/i18n/locales/fr-BE/knowledge.json index ddb09ef..330dcd9 100644 --- a/frontend/src/i18n/locales/fr-BE/knowledge.json +++ b/frontend/src/i18n/locales/fr-BE/knowledge.json @@ -23,11 +23,11 @@ "checkout-procedure": "Contrôles obligatoires au départ" }, "statistics": { - "verifiedIndexed": "publiées activement et contenu vérifié", + "verifiedIndexed": "correspondance exacte et publication active", "sourceDocuments": "documents sources dans cette langue", "reportedSynced": "synchronisation signalée par n8n", "reportedFailed": "échecs de synchronisation signalés", - "lastSync": "Dernier rapport de synchronisation : {{when}}. L’état de l’index est contrôlé indépendamment via la version RAGcore active et l’empreinte de contenu de chaque source gérée.", + "lastSync": "Dernier rapport de synchronisation : {{when}}. L’état de l’index est contrôlé indépendamment via l’identité exacte et la version RAGcore active de chaque source gérée.", "noSyncReport": "Aucun rapport de synchronisation reçu. Les preuves d’indexation sont contrôlées séparément via les versions RAGcore actives." }, "providerNote": "Cette démo répond à partir d'un petit ensemble fixe de procédures indexées — pas d'une connexion RAGcore en direct. Un backend RAGcore en direct reprendra plus tard la même interface sans changer le fonctionnement de cette page.", diff --git a/frontend/src/i18n/locales/nl-BE/knowledge.json b/frontend/src/i18n/locales/nl-BE/knowledge.json index ae0c33a..bdf528e 100644 --- a/frontend/src/i18n/locales/nl-BE/knowledge.json +++ b/frontend/src/i18n/locales/nl-BE/knowledge.json @@ -23,11 +23,11 @@ "checkout-procedure": "Verplichte vertrekcontroles" }, "statistics": { - "verifiedIndexed": "actief gepubliceerd en inhoudelijk geverifieerd", + "verifiedIndexed": "exact gevonden en actief gepubliceerd", "sourceDocuments": "brondocumenten in deze taal", "reportedSynced": "sync door n8n gerapporteerd", "reportedFailed": "syncfouten gerapporteerd", - "lastSync": "Laatste syncrapport: {{when}}. De indexstand wordt onafhankelijk gecontroleerd via de actieve RAGcore-versie en inhoudshash van elke beheerde bron.", + "lastSync": "Laatste syncrapport: {{when}}. De indexstand wordt onafhankelijk gecontroleerd via de exacte bronidentiteit en actieve RAGcore-versie.", "noSyncReport": "Nog geen syncrapport ontvangen. Indexbewijs wordt afzonderlijk via de actieve RAGcore-versies gecontroleerd." }, "providerNote": "Deze demo beantwoordt vanuit een kleine, vaste set geïndexeerde procedures — geen live RAGcore-koppeling. Een live RAGcore-backend zal later dezelfde interface overnemen, zonder dat deze pagina verandert.",