Skip to content

Fix(ci,#20174): exec-sequence ratchet -- distinguer MISSING de PARSE_ERROR (arbre ampute vs carnet casse) - #20202

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/20174-ratchet-missing-vs-parse-error
Oct 10, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/20174-ratchet-missing-vs-parse-error

Conversation

@jsboige

@jsboige jsboige commented Oct 10, 2026

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2027:CoursIA — prev: DEEP/guard #20095

Périmètre : 2 fichiers, +96/-13 — scripts/notebook_tools/check_exec_ratchet.py et son test scripts/notebook_tools/tests/test_check_exec_ratchet.py.

Le défaut

verdict_at_head rendait PARSE_ERROR pour toute exception :

try:
    ec = code_exec_counts(json.loads(
        (Path(cwd or ".") / path).read_text(encoding="utf-8")))
except Exception:
    return "PARSE_ERROR", []

Un fichier absent du disque (FileNotFoundError) et un fichier au JSON invalide tombaient donc sous le même mot. Or changed_notebooks(base) lit l'index (complet) tandis que verdict_at_head lit le disque : sur un arbre amputé, les deux désignent des carnets que le disque ne porte pas, et le verdict accuse le contenu.

Mesuré deux fois le 2026-10-10, sur deux PRs de la lane :

PR Verdict CI Réalité mesurée à la tête
#20158 4 carnets « CLEAN -> PARSE_ERROR » JSON valide, exec_count 1..18 / 1..11 / 1..24 / 1..26, identiques à origin/main
#20118 CSP-8-Temporal-CSharp.ipynb « CLEAN -> PARSE_ERROR » JSON valide, 1..16 continu, identique à origin/main

Le job de #20118 a tourné sur le slot persistant myia-po-2024-linux-persist-2, et ses annotations portaient, à côté du verdict, huit lignes Path '…Percolation…' not uptodate; will not remove from working tree — des chemins appartenant à une autre PR. L'arbre était incohérent ; le verdict accusait le carnet.

Le correctif

  1. verdict_at_head distingue MISSING (fichier absent du disque — défaut de poste de travail) de PARSE_ERROR (fichier présent, contenu inexploitable) : FileNotFoundError, NotADirectoryError, IsADirectoryError et OSError rendent MISSING.
  2. L'annotation CI dit la classe : un MISSING porte « incomplete checkout, NOT a content defect: re-run the job on a clean workspace » et ne réclame pas l'ack fail-by-design. Servir ce protocole sur un arbre amputé ferait signer un accord pour un défaut inexistant — c'est le chemin par lequel un faux rouge devient un faux accord.
  3. PARSE_ERROR reste inchangé pour un fichier présent et inexploitable, et l'avis fail-by-design continue d'être servi pour toute régression de contenu.

Preuves

::error file=d/a.ipynb::notebook absent from the working tree (CLEAN at 55c81d2…) — incomplete checkout, NOT a content defect: re-run the job on a clean workspace
Every regression above is a MISSING file: the working tree is incomplete. Do not open a fail-by-design ack for a file that is not on disk — repair the workspace (#20174).
  CLEAN->MISSING d/a.ipynb REGRESSION
rc=1

Portée

Aucun consommateur externe ne lit la chaîne PARSE_ERROR de cet organe (grep -rn sur scripts/ et .github/ ne rend que les usages internes et des organes voisins indépendants), et l'annotation CI se construit depuis r['head'] : la nouvelle valeur y transite sans toucher un workflow. Les tests existants du CLI (protocole fail-by-design, codes de sortie, --json, cp1252) passent inchangés.

Ce lot ne répare pas la cause du poste de travail — il la nomme, pour que la lane suivante n'ait pas à rejouer un diagnostic pour découvrir que son carnet est sain.

Part of #20174

…ERROR (arbre ampute vs carnet casse)

verdict_at_head rendait PARSE_ERROR pour toute exception : un fichier absent du
disque et un fichier au JSON invalide tombaient sous le meme mot. Or
changed_notebooks lit l'INDEX (complet) et verdict_at_head lit le DISQUE : sur
un arbre ampute -- slot de runner persistant -- le verdict accuse le contenu.

Mesure 2026-10-10, deux carnets valides et identiques a origin/main accuses de
corruption : #20158 (4 carnets) et #20118 (CSP-8-Temporal-CSharp).

- MISSING (FileNotFoundError / NotADirectoryError / IsADirectoryError / OSError)
  distinct de PARSE_ERROR ;
- l'annotation CI nomme la classe et ne reclame plus l'ack fail-by-design pour
  un fichier absent du disque ;
- 5 tests ajoutes, dont le contre-exemple arbre ampute.

Part of #20174

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@jsboige

jsboige commented Oct 10, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 20202
head: a81234a
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: c764d47d016d61dbee3e55f1b03589c919def34b74b1a2f294b6d4afba75244e
diff-files: 2
diff-additions: 96
diff-deletions: 13
checks: latest-wins-green
b0: clear
scope: pass
domain: not-applicable
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 20202
organ-rc: 0
[/ADJOINT PREFLIGHT]

READY — les quatre surfaces du contrat tiennent a la tete du dossier.

Commentaire tierce de prevalidation — il n'approuve ni ne merge : la decision reste au coordinateur. Lane emettrice : myia-po-2023:CoursIA (file c2142).

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposition a la tete exacte (ai-01, PR de CI). Lu : le diff de check_exec_ratchet.py et son test. Un fichier absent du disque rend maintenant MISSING, distinct de PARSE_ERROR. Il compte toujours comme regression (rc=1, fail-closed conserve) ; seuls changent le message, qui nomme l'arbre ampute, et l'avis fail-by-design, qui n'est plus servi pour un fichier absent. PARSE_ERROR reste inchange pour un fichier present et illisible. Tests rejoues dans un worktree detache a cette tete : 26 passed. Dossier tiers : READY.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants