Constat
scripts/notebook_tools/check_kernel_drift.py (job Kernel drift guard (base vs PR)) rend un faux positif mesuré sur toute PR dont un carnet ré-exécuté porte une cellule injected-parameters de papermill.
Instance fondatrice : PR #17145, tête cc2d77b529, check-run Kernel drift guard (base vs PR) = FAILURE.
Mesure (reproduite avec l'organe lui-même)
python scripts/notebook_tools/check_kernel_drift.py origin/main --explain --json
{"findings":[{"notebook":".../03-3-ComfyUI-Video-Workflows.ipynb",
"kernel_diffs":[],
"signature_drift_cells":["bec0f46c"],
"base_kernel":{"kernelspec_name":"python3","language_version":"3.13.3"},
"head_kernel":{"kernelspec_name":"python3","language_version":"3.13.3"},
"body_exemption":false}],
"body_exempts":false} -> exit 1
Aucune dérive d'output : les 12 cellules code communes aux deux versions ont des signatures float égales au tuple, et le carnet ne produit aucune sortie de tableau flottant (0 cellule à signature non vide). kernel_diffs est vide, les métadonnées de noyau sont identiques.
La cellule signalée bec0f46c porte 0 sortie : sa signature vaut () des deux côtés. Elle est présente uniquement dans la PR parce que c'est la cellule injected-parameters — la base en portait une autre (2a6a4d49). Papermill remplace la cellule injected-parameters existante à chaque ré-exécution, et nbformat 4.5 attribue un id neuf au remplaçant.
Cause racine
diff_signatures(), branche d'alignement par id :
# Added code cells (only in head)
for cid in sorted(set(head_ids.keys()) - set(base_ids.keys())):
diffs.append(cid)
Toute cellule code présente seulement dans head est ajoutée aux dérives sans condition sur sa signature. Une cellule qui ne porte aucune signature float ne peut pourtant pas être une dérive de repr float — le prédicat est plus large que la propriété qu'il prétend détecter.
Le couple (un id retiré, un id ajouté) est l'empreinte normale d'une ré-exécution papermill. La classe se déclenche donc à chaque ré-exécution d'un carnet portant une cellule injected-parameters, c'est-à-dire très souvent sur ce dépôt ; la PR doit alors écrire une section ## Diagnostic dérive (C.4) pour un écart qui n'existe pas.
Correctif borné proposé
Ne signaler une cellule ajoutée que si elle porte effectivement une signature non vide :
for cid in sorted(set(head_ids.keys()) - set(base_ids.keys())):
h_idx = head_ids[cid]
if h_idx < len(head_sig) and head_sig[h_idx]:
diffs.append(cid)
Le correctif ne peut pas manquer une dérive réelle : une dérive de repr float exige une signature non vide. Une cellule ajoutée qui produit un tableau flottant reste signalée.
Variante à trancher en review : exclure nommément les cellules taguées injected-parameters (artefact d'exécution, pas du contenu auteur). Le prédicat par signature vide est plus général et ne couple pas l'organe à une convention d'un outil tiers ; la variante par tag est plus explicite. Les deux sont testables.
Acceptance
Contournement en attendant
Une section ## Diagnostic dérive dans le body de la PR lève le rouge (acknowledged: true -> rc 0, voie --json). C'est la porte prévue par le workflow, et elle est honnête quand le diagnostic est mesuré — mais elle documente un écart qui n'existe pas.
See #16081, #16679 (même famille de défauts d'alignement de l'organe).
Constat
scripts/notebook_tools/check_kernel_drift.py(jobKernel drift guard (base vs PR)) rend un faux positif mesuré sur toute PR dont un carnet ré-exécuté porte une celluleinjected-parametersde papermill.Instance fondatrice : PR #17145, tête
cc2d77b529, check-runKernel drift guard (base vs PR)=FAILURE.Mesure (reproduite avec l'organe lui-même)
{"findings":[{"notebook":".../03-3-ComfyUI-Video-Workflows.ipynb", "kernel_diffs":[], "signature_drift_cells":["bec0f46c"], "base_kernel":{"kernelspec_name":"python3","language_version":"3.13.3"}, "head_kernel":{"kernelspec_name":"python3","language_version":"3.13.3"}, "body_exemption":false}], "body_exempts":false} -> exit 1Aucune dérive d'output : les 12 cellules code communes aux deux versions ont des signatures float égales au tuple, et le carnet ne produit aucune sortie de tableau flottant (0 cellule à signature non vide).
kernel_diffsest vide, les métadonnées de noyau sont identiques.La cellule signalée
bec0f46cporte 0 sortie : sa signature vaut()des deux côtés. Elle est présente uniquement dans la PR parce que c'est la celluleinjected-parameters— la base en portait une autre (2a6a4d49). Papermill remplace la celluleinjected-parametersexistante à chaque ré-exécution, et nbformat 4.5 attribue un id neuf au remplaçant.Cause racine
diff_signatures(), branche d'alignement par id :Toute cellule code présente seulement dans head est ajoutée aux dérives sans condition sur sa signature. Une cellule qui ne porte aucune signature float ne peut pourtant pas être une dérive de repr float — le prédicat est plus large que la propriété qu'il prétend détecter.
Le couple (un id retiré, un id ajouté) est l'empreinte normale d'une ré-exécution papermill. La classe se déclenche donc à chaque ré-exécution d'un carnet portant une cellule
injected-parameters, c'est-à-dire très souvent sur ce dépôt ; la PR doit alors écrire une section## Diagnostic dérive(C.4) pour un écart qui n'existe pas.Correctif borné proposé
Ne signaler une cellule ajoutée que si elle porte effectivement une signature non vide :
Le correctif ne peut pas manquer une dérive réelle : une dérive de repr float exige une signature non vide. Une cellule ajoutée qui produit un tableau flottant reste signalée.
Variante à trancher en review : exclure nommément les cellules taguées
injected-parameters(artefact d'exécution, pas du contenu auteur). Le prédicat par signature vide est plus général et ne couple pas l'organe à une convention d'un outil tiers ; la variante par tag est plus explicite. Les deux sont testables.Acceptance
injected-parametersidA, head avec la même cellule idB(0 sortie) -> 0 finding, rc 0.scripts/notebook_tools/tests/test_check_kernel_drift.pyrestent verts.Contournement en attendant
Une section
## Diagnostic dérivedans le body de la PR lève le rouge (acknowledged: true->rc 0, voie--json). C'est la porte prévue par le workflow, et elle est honnête quand le diagnostic est mesuré — mais elle documente un écart qui n'existe pas.See #16081, #16679 (même famille de défauts d'alignement de l'organe).