Skip to content

feat: report effective model identities and capabilities for reproducible local runs #734

Open

Description

@cdeust

Problem and evidence

The default embedding revision is pinned and reranker file SHA256 can be computed. Reranker loading uses its name/cache; absent models can engage a documented fallback. Reproducible offline/performance claims need one effective manifest joining these facts with actual backend capabilities. A configured model name alone does not identify its bytes.

Acceptance evidence

  • Expose engine/plugin identity, backend, model revision/digest, device and actual inference mode without content or sensitive configuration.
  • Retain the manifest beside every measured result and native receipt.
  • Verify provisioned models against their supported identity and report missing/corrupt/incompatible states.
  • Demonstrate memory operations with networking disabled after provisioning and label fallback behavior.
  • Derive resource/latency budgets from measured workloads; do not promote a fallback score as a full-model score.

Scope and related work

#705 covers downloads/startup; #685 silent degradation; #708 default-backend quality. This joins model identity and capabilities into a reproducibility artifact.

Raised by the global Hindsight/Cortex audit. The target is a measurable local-first experience with the same supported semantics in Claude and Codex. Acceptance criteria describe a target, not current conformance. Static findings refer to the pinned source; probes identify their boundary.

Primary references

mcp_server/infrastructure/embedding_model_lifecycle.py:34; mcp_server/core/reranker.py:70; mcp_server/infrastructure/reranker_cache.py:29; PRIVACY.md:73

Activity

  1. cdeust commented on Nov 6, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : tranche 1 livrée dans #905 (Refs #734, l'issue reste ouverte).

    #905 ajoute docs/audits/model-identity-inventory-2026-11-06.md : quels faits d'identité de l'embedding et du reranker un run local enregistre, où chacun est exposé, et où une valeur enregistrée ne décrit pas ce que le run a servi. Le constat principal, reproduit par une sonde : benchmarks/lib/write_manifest.py enregistre la révision épinglée embedding_model_revision même quand le moteur est en PACKAGE_ABSENT et sert des embeddings de repli. Le sha256 du reranker est enregistré mais jamais vérifié.

    Tranches restantes :

    1. Enregistrer le mode et le ModelState réellement servis dans les deux manifestes, et la révision seulement à l'état LOADED.
    2. Un manifeste effectif unique (identité moteur/plugin de doctor_artifact, backend, modèles, révision et digests, devices, mode), rendu par cortex doctor et par les benchmarks.
    3. Vérifier les modèles provisionnés contre une identité épinglée (sha256 attendu du reranker, digest des fichiers de l'embedding) et signaler les états absent, corrompu ou incompatible.
    4. Un reçu des opérations mémoire réseau coupé après provisionnement, chaque résultat étiqueté avec son mode.

    Non vérifié : un moteur neural LOADED et un FlashRank chargé (téléchargements impossibles via le proxy de ce conteneur), GPU, PostgreSQL.


    Generated by Claude Code

  2. cdeust commented on Nov 10, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : tranche 2 dans #966 (Refs #734, l'issue reste ouverte).

    • Cause : EmbeddingEngine.revision renvoie l'épingle du constructeur quel que soit l'état ; MANIFEST.json enregistrait donc 1110a243…4d41 pour un run PACKAGE_ABSENT servi en repli, et le manifeste repro (LongMemEval, LoCoMo, BEAM) n'avait aucune identité d'embedding.
    • Correctif (commit aabeda9) : benchmarks/lib/embedding_identity.py lit mode puis model_state, et ne donne la révision qu'à l'état LOADED. Les deux manifestes portent embedding_mode, embedding_model_state, embedding_model_name, embedding_model_revision.
    • Tests : 5 nouveaux tests (le test de câblage échoue sans la modification) ; tests_py/benchmarks/ 394 passed, 13 skipped.
    • Non vérifié : un moteur neural LOADED (torch non téléchargeable via le proxy du conteneur) ; CI de fix(bench): manifests record the embedding a run served, not the pin (#734, slice 2) #966 en cours.

    Tranches restantes (audit) : manifeste effectif unique rendu par cortex doctor ; vérification des modèles provisionnés contre une identité épinglée ; reçu des opérations mémoire réseau coupé.


    Generated by Claude Code

  3. cdeust commented on Nov 10, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 3 est dans #972 (Refs #734, l'issue reste ouverte).

    • Cause : le sha256 du fichier ONNX du reranker était enregistré dans les deux manifestes, mais rien ne le comparait. Un fichier modifié ou corrompu que FlashRank charge quand même donnait reranker_state: loaded, et aucune surface ne le signalait.
    • Correctif (commit 9d25ef3) :
      • core/reranker_identity.py classe le digest comme absent, verified ou mismatch par rapport à d3dd7b09…41d1. C'est la seule valeur parmi les 131 résultats committés ; la source citée est benchmarks/results/repro/20261014T232318Z/MANIFEST.json.
      • Nouveau check optionnel cortex doctor Reranker weights identity, sur les deux backends. Il lit le fichier en cache et ne télécharge, ne supprime ni ne charge aucun modèle.
      • Les deux manifestes enregistrent reranker_model_identity.
    • Tests : 9 nouveaux tests. Les suites liées donnent 456 passed, 15 skipped. Le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié :

    Tranches restantes :

    1. Un manifeste effectif unique, rendu par cortex doctor et par les benchmarks.
    2. Le digest des fichiers du snapshot de l'embedding, comparé à une identité épinglée.
    3. Un reçu des opérations mémoire exécutées réseau coupé.

    C'est la troisième tentative sur cette issue. Les deux PR précédentes (#905, #966) sont fusionnées.


    Generated by Claude Code

  4. cdeust commented on Nov 10, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 4 est dans #974 (Refs #734, l'issue reste ouverte).

    • Cause : aucun fichier du cache de l'embedding n'était haché. Un model.safetensors tronqué ou modifié sous le snapshot épinglé n'était signalé nulle part.
    • Correctif (commit 9f738b8) : le cache Hugging Face nomme le blob d'un fichier LFS par le sha256 que le Hub a renvoyé au téléchargement (blobs/<sha256>, huggingface_hub/file_download.py en 0.36.2 et 1.33.0). Le nouveau check optionnel cortex doctor Embedding weights identity compare le digest des octets à ce nom. Il distingue quatre états : absent, unverifiable (une copie sans lien), verified et mismatch. Il ne télécharge, ne supprime ni ne charge rien.
    • Tests : 17 nouveaux tests. Les suites liées donnent 508 passed. 3 échecs existent aussi sur main dans ce conteneur, qui n'a pas sentence-transformers. Le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié :

    Tranches restantes :

    1. Un manifeste effectif unique, rendu par cortex doctor et par les benchmarks.
    2. Un reçu des opérations mémoire exécutées réseau coupé.

    C'est la quatrième tentative sur cette issue. Les trois PR précédentes (#905, #966, #972) sont fusionnées.


    Generated by Claude Code

  5. cdeust commented on Nov 11, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 5 est dans #990 (Refs #734, l'issue reste ouverte).

    • Cause : les faits qui identifient une exécution étaient répartis sur cinq surfaces : l'artefact, les deux checks de poids, le backend et les champs d'embedding des manifestes. Aucune ne les réunissait.
    • Correctif (commit 966b4f0) : mcp_server/doctor_manifest.py construit un manifeste unique (schema: 1). Il contient l'artefact, le backend sélectionné, et pour chaque modèle le nom, la révision ou le digest attendu, l'état des poids sur disque et ce qui a été servi. Il ne contient aucun chemin, aucune URL ni aucun réglage de connexion. cortex-doctor manifest l'affiche, et write_manifest.py comme _repro.py l'intègrent sous runtime_manifest.
    • Tests : 15 nouveaux tests. Les suites qui importent les modules touchés donnent 566 passed. Ruff, le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié :

    Tranche restante :

    1. Un reçu des opérations mémoire exécutées réseau coupé après provisionnement, chaque résultat étiqueté avec le mode dans lequel il a tourné.

    Hors manifeste pour l'instant : le device effectivement résolu par l'embedding et le provider ONNX du reranker. Seul device_requested est enregistré.

    C'est la cinquième tentative sur cette issue. Les quatre PR précédentes (#905, #966, #972, #974) sont fusionnées.


    Generated by Claude Code

  6. cdeust commented on Nov 11, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 6 est dans #991 (Refs #734, l'issue reste ouverte).

    • Livré (commit 762bb4d) : python -m benchmarks.lib.offline_receipt --out receipt.json exécute trois remember et un recall par les handlers de production. L'exécution a lieu dans un interpréteur neuf, sur un store SQLite jetable, avec un garde réseau installé au niveau socket avant l'import de mcp_server. Chaque opération est étiquetée avec le mode et le ModelState de l'embedding, l'état du reranker et ses tentatives réseau. Le reçu contient effective_manifest et un verdict (offline, network_attempted ou failed), ainsi que la liste des opérations servies en repli.
    • Cause racine trouvée en chemin : la première version laissait passer tout le loopback. Dans ce conteneur, HTTPS_PROXY vaut http://127.0.0.1:<port>, et le recall a téléchargé FlashRank par ce proxy pendant que le reçu affichait offline. Le garde refuse maintenant tout proxy que renvoie urllib.request.getproxies(). L'enfant tourne aussi sans variables *_proxy, ce qui permet au reçu de nommer l'hôte réel.
    • Constat : sur une machine où FlashRank n'est pas provisionné et où CORTEX_RERANKER_OFFLINE n'est pas positionné, le premier recall tente huggingface.co:443. Avec CORTEX_RERANKER_OFFLINE=1, le verdict est offline avec 0 tentative.
    • Tests : 21 nouveaux tests. tests_py/benchmarks/ et test_doctor_manifest.py donnent 440 passed. Les tests d'architecture et d'invariants donnent 100 passed. Ruff, le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié : une machine réellement provisionnée (neural LOADED, FlashRank chargé), macOS et Windows, PostgreSQL, la suite complète, la CI de feat(benchmarks): receipt of memory operations with networking disabled (#734, slice 6) #991.

    Tranches restantes :

    1. Le device réellement résolu par l'embedding et le provider ONNX du reranker.
    2. Des budgets de ressources et de latence dérivés de charges mesurées (recoupe feat: expose local operation receipts with attributable resource consumption #733).

    C'est la sixième tentative sur cette issue. Les cinq PR précédentes (#905, #966, #972, #974, #990) sont fusionnées.


    Generated by Claude Code

  7. cdeust commented on Nov 11, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 7 est dans #993 (Refs #734, l'issue reste ouverte).

    • Cause : les manifestes n'enregistraient que device_requested. Or auto est résolu par _detect_device, et un échec GPU recharge le modèle sur CPU (_fallback_to_cpu). Le réglage ne disait donc pas où les vecteurs avaient été calculés.
    • Correctif (commit 0fe4814) : EmbeddingEngine.device_served donne le device du modèle chargé, ou None. embedding_identity_fields l'enregistre sous embedding_device (None hors LOADED), dans les deux manifestes et dans le reçu hors ligne.
    • Tests : 1 nouveau test sur le moteur, et les tests d'identité étendus. Les suites liées donnent 584 passed. Les 3 échecs restants existent aussi sur main dans ce conteneur, qui n'a pas sentence-transformers. Ruff, le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié : un vrai modèle sur GPU, macOS, Windows, PostgreSQL, la CI de feat(benchmarks): record the device the embedding model runs on (#734, slice 7) #993.

    Tranches restantes :

    1. Le provider ONNX effectif du reranker. FlashRank n'est pas installable ici : il faut lire sa création de session ONNX avant d'implémenter quoi que ce soit.
    2. Des budgets de ressources et de latence dérivés de charges mesurées (recoupe feat: expose local operation receipts with attributable resource consumption #733, dont la PR feat(telemetry): five memory tools record one sample per call (#733) #989 est en hold).

    C'est la septième tentative sur cette issue. Les six PR précédentes (#905, #966, #972, #974, #990, #991) sont fusionnées.


    Generated by Claude Code

  8. cdeust commented on Nov 11, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : les correctifs du reçu hors-ligne (#991) sont dans #994 (Refs #734, l'issue reste ouverte).

    Ce sont les notes de la revue de #991 et les trois constats Codex P2, vérifiés un par un dans le code :

    • le verdict exige qu'un remember ait stocké et qu'un recall ait retrouvé une mémoire stockée ;
    • un proxy localhost est refusé aussi aux adresses qu'il résout ;
    • les processus enfants, dont le téléchargement de l'embedding, sont refusés et comptés comme tentatives ;
    • un échec d'inférence du reranker classe le recall en repli, et les remember ne sont plus classés en repli à cause du reranker.

    Commit 690b3ec : 27 tests sur le reçu, dont 5 échouent sur le code de #991, et 447 tests passent sur les suites liées. Non vérifié : une machine provisionnée, les proxys système macOS et Windows, la CI de #994.


    Generated by Claude Code

  9. cdeust commented on Nov 11, 2026

    @cdeust
    OwnerAuthor

    CI autopilot : la tranche 8 est dans #995 (Refs #734, l'issue reste ouverte).

    • Cause : FlashRank 0.2.10 crée ort.InferenceSession(path) sans argument providers. C'est donc onnxruntime qui les choisit, et aucun manifeste ne disait où l'inférence du reranker avait tourné. La liste des providers disponibles ne répond pas à la question : sur onnxruntime 1.28.0, une sonde sur un vrai modèle donne get_available_providers() = ['AzureExecutionProvider', 'CPUExecutionProvider'], alors que la session a get_providers() = ['CPUExecutionProvider'].
    • Correctif (commit 3291cce) : RerankerStatus.providers contient le get_providers() de la session chargée, dans l'ordre de priorité. Il vaut None sans session ONNX : chargement en échec, chargement non tenté, ou ranker listwise llama-cpp. Les deux manifestes et le reçu hors ligne l'enregistrent sous reranker_providers.
    • Tests : 3 nouveaux tests, qui échouent sans la modification. Les suites liées donnent 4404 passed et 1 échec, qui existe aussi sur main dans ce conteneur (un test de permissions lancé en root). Ruff, le gate de craftsmanship et check_doc_claims passent.
    • Non vérifié : un vrai modèle FlashRank chargé (huggingface.co est inaccessible, les tests utilisent une session simulée), un provider GPU, macOS et Windows, la CI de feat(benchmarks): record the ONNX providers the reranker runs on (#734, slice 8) #995.

    Tranche restante :

    1. Des budgets de ressources et de latence dérivés de charges mesurées. Cette tranche recoupe feat: expose local operation receipts with attributable resource consumption #733, dont la PR feat(telemetry): five memory tools record one sample per call (#733) #989 attend une relance humaine de Claude review.

    C'est la huitième tentative sur cette issue. Les sept PR précédentes sont fusionnées.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions