Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 65 additions & 11 deletions docs/PARCOURS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Le catalogue généré (`COURSE_CATALOG.generated.json`) porte aujourd'hui un ch

1. **Maturité éditoriale** — où en est la *prose pédagogique* ? (de DRAFT = jamais relu à FINAL = relu, stable, prêt à publier).
2. **Reproductibilité** — le notebook a-t-il *réellement tourné* et avec quel niveau de garantie ? (de UNTESTED = aucune cellule exécutée à REPRODUCED = ré-exécuté de bout en bout avec succès, horodaté).
3. **Revue scientifique** — la *substance technique* a-t-elle été validée et par qui ? (de UNREVIEWED = auteur seul à FORMALLY_VERIFIED = preuve formelle ou peer-review externe).
3. **Confiance scientifique** — quel *risque* la substance prend-elle sur ce qu'elle affirme ? (de UNASSESSED = pas d'appréciation portée à RESEARCH = recherche active, contenu explicitement en cours d'élaboration).

Mélanger ces axes en une seule étiquette (PRODUCTION, BETA…) a trois défauts :
- **Illisible** : « BETA » ne dit pas si le notebook a réellement exécuté, ni si la substance est revue — il dit juste « pas tout à fait finalisé ».
Expand Down Expand Up @@ -49,12 +49,50 @@ Mélanger ces axes en une seule étiquette (PRODUCTION, BETA…) a trois défaut

### Axe 3 — `scientific_review` (revue scientifique)

| Valeur | Définition | Critère vérifiable |
|--------|-----------|--------------------|
| `UNREVIEWED` | Aucun passage en revue hors l'auteur | Pas de signal `scientific_reviewed_by` ni de PR/discussion de substance attachée |
| `AUTHOR_REVIEWED` | L'auteur a relu sa propre substance (cross-check, sanity-checks) | Présence d'une note « Self-review » dans le notebook OU signal PR auteur `self-reviewed` |
| `PEER_REVIEWED` | Relecture par ≥1 agent tiers du cluster ou reviewer externe | `scientific_reviewed_by` non-null ET ≠ auteur du dernier commit |
| `FORMALLY_VERIFIED` | Preuve formelle (Lean, Coq, Agda) ou benchmark reproductible validé | Présence d'un fichier `.lean` companion OU `lake build SUCCESS` daté OU benchmark QC multi-seed ≥4 seeds |
**L'axe mesure le risque du contenu, pas la provenance de sa relecture** (#14831,
sign-off user 2026-09-21). L'échelle précédente (`UNREVIEWED` → `AUTHOR_REVIEWED` →
`PEER_REVIEWED` → `FORMALLY_VERIFIED`) classait *qui avait relu, avec quelle rigueur
formelle*. Elle était **inversée dans ses effets** : une série de recherche active relue
par des pairs atteignait le haut de l'échelle, pendant qu'un notebook de cours classique,
universellement admis et sans aucun risque, restait `UNREVIEWED` faute de reviewer nommé.
Elle reposait de plus sur le compte de `sorry`, un indicateur qui ne concerne qu'une
poignée de notebooks Lean, pour piloter un axe couvrant tout le corpus.

| Valeur | Définition | D'où elle vient |
|--------|-----------|-----------------|
| `UNASSESSED` | Aucune appréciation portée. **Ce n'est pas un mauvais score** : c'est l'absence de jugement, et c'est le défaut honnête. | défaut ; aucune entrée de registre |
| `ESTABLISHED` | Contenu communément admis et universellement pratiqué. Le notebook ne prend aucun risque sur ce qu'il affirme. | `confidence: established` au registre |
| `ADVANCED` | Protocoles plus avancés, exécutions moins contrôlées, théories récentes, interprétations discutables. Le contenu tient, mais il engage. | `confidence: advanced` |
| `RESEARCH` | Recherche active — ICT au premier chef. Le contenu est explicitement en cours d'élaboration, et le dire est la seule position honnête. | `confidence: research` |

Une valeur non reconnue retombe sur `UNASSESSED` (**fail-CLOSED**) : c'est la propriété
qui empêche le label-gaming.

#### L'appréciation se périme quand le code bouge

Une appréciation porte sur ce que le notebook **calcule et affirme**. Si le calcul change,
elle ne porte plus sur ce qui est là. Le catalogue émet donc `scientific_review_stale:
true` lorsque l'empreinte du code diffère du `reviewed_code_sha` enregistré au moment de
la revue — **la grade est conservée**, seul le drapeau bascule : la perdre effacerait
l'information (« personne n'a jamais apprécié ») alors que le fait est autre (« quelqu'un
a apprécié, puis le code a bougé »).

Cela met l'audit scientifique en **régime permanent**, ce qui est l'effet recherché : une
nouvelle revue est due, sous le protocole de [SCIENTIFIC_REVIEW_CARD.md](notebook-metadata/SCIENTIFIC_REVIEW_CARD.md).

L'empreinte exclut délibérément trois choses, chacune pour une raison mesurée :

- **le markdown** — la campagne de densification a modifié 178 notebooks en trois semaines
sans toucher une ligne de code ; l'inclure rétrograderait tout le corpus au premier
passage, et une rétrogradation qui frappe tout ne signale plus rien ;
- **les sorties** — une ré-exécution les change sans changer ce que le notebook affirme ;
- **`execution_count`** — pur artefact d'ordre d'exécution.

C'est une empreinte de **contenu**, jamais un blob SHA git : un squash-merge réécrit les
blobs et tuerait l'ancre à chaque merge (#11919).

`sorry_free` et `scientific_reviewed_by` restent rendus **comme preuves à côté** — ils ne
pilotent plus la grade.

---

Expand All @@ -63,7 +101,7 @@ Mélanger ces axes en une seule étiquette (PRODUCTION, BETA…) a trois défaut
Le champ `maturity` monolithique actuel reste **présent** dans `COURSE_CATALOG.generated.json` pour ne casser aucun consommateur existant (README, dashboards, scripts tiers). Il est désormais **calculé comme l'agrégat** des 3 axes, selon la règle :

```
editorial == "FINAL" AND reproducibility in ("EXECUTED", "REPRODUCED") AND scientific_review in ("PEER_REVIEWED", "FORMALLY_VERIFIED")
production_signed (tampon du responsable pédagogique, cf docs/notebook-metadata/production-scope.md)
→ maturity = "PRODUCTION"
editorial in ("BETA", "FINAL") AND reproducibility in ("EXECUTED", "REPRODUCED")
→ maturity = "BETA"
Expand All @@ -75,13 +113,29 @@ sinon
→ maturity = "DRAFT"
```

**Le consommateur qui veut plus de granularité** lit directement `editorial`, `reproducibility`, `scientific_review`. Celui qui veut l'ancien label lit `maturity`. Aucun breaking change.
**`PRODUCTION` ne se dérive plus d'aucune combinaison d'axes** (#14831, sign-off user
2026-09-21). Il ne décrit pas une propriété mesurable du fichier : il dit que le
responsable pédagogique a **apposé son tampon**, et juge le notebook finalisé pour être
utilisé en cours **par d'autres**. Le calculer revenait à fabriquer une signature.

Le signal vient donc de la colonne « Verdict » de
[production-scope.md](notebook-metadata/production-scope.md), qui est la surface de
décision. Un notebook non tranché reste `BETA` — et c'est le verdict **correct**, pas un
manque : l'auteur enseigne lui-même sur les beta et les beta-teste avec ses étudiants.

`scientific_review` reste **nécessaire mais pas suffisant** pour `PRODUCTION` : il est
exigé par le validateur de périmètre, pas par l'agrégat — un axe qui *gate* ne doit pas
être le même objet que l'axe qui *décrit*.

**Le consommateur qui veut plus de granularité** lit directement `editorial`,
`reproducibility`, `scientific_review` (+ `scientific_review_stale`). Celui qui veut
l'ancien label lit `maturity`. Aucun breaking change.

## Statut séparé — non touché par ce schéma

Le champ `status` (`READY`, `DEMO`, `RESEARCH`, `BROKEN`) reste **orthogonal** aux 3 axes maturité. Un notebook peut être :
- `editorial=FINAL` + `reproducibility=REPRODUCED` + `scientific_review=PEER_REVIEWED` + `status=BROKEN` (ex : notebook qui marchait mais dont une dépendance externe est cassée) ;
- `editorial=ALPHA` + `reproducibility=EXECUTED` + `scientific_review=AUTHOR_REVIEWED` + `status=DEMO` (ex : démo scientifique sans valeur pédagogique aboutie).
- `editorial=FINAL` + `reproducibility=REPRODUCED` + `scientific_review=ESTABLISHED` + `status=BROKEN` (ex : notebook qui marchait mais dont une dépendance externe est cassée) ;
- `editorial=ALPHA` + `reproducibility=EXECUTED` + `scientific_review=RESEARCH` + `status=DEMO` (ex : démo scientifique sans valeur pédagogique aboutie).

`status` répond à « *peut-on le faire tourner en l'état ?* », les 3 axes répondent à « *où en est sa substance ?* ». Séparer les deux est une décision architecturale stable (issue #8051 acceptance critère 2).

Expand Down
70 changes: 63 additions & 7 deletions docs/notebook-metadata/SCIENTIFIC_REVIEW_CARD.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
# SCIENTIFIC_REVIEW_CARD — Template de revue scientifique

**Statut** : template canonique (c.997)
**Statut** : template canonique (c.997, refondu #14831 — sign-off user 2026-09-21)
**Usage** : copié/adapté par chaque reviewer qui ajoute une entrée à [scientific-review-registry.md](scientific-review-registry.md)
**Référence scope** : [scientific-review-registry.md §3.2](scientific-review-registry.md#32-portée-de-la-revue)
**Échelle** : [PARCOURS.md — axe 3](../PARCOURS.md#axe-3--scientific_review-revue-scientifique)

> **Quand cette carte se remplit.** À la première appréciation d'un notebook, et
> **chaque fois que le catalogue rend `scientific_review_stale: true`** — c'est-à-dire
> chaque fois que le *code* du notebook a changé depuis la dernière revue. C'est un
> régime d'**audit permanent**, et c'est voulu : une appréciation porte sur ce que le
> notebook calcule, donc elle ne survit pas à un changement de calcul.
>
> Lister ce qui est dû :
> ```bash
> python scripts/audit/check_scientific_review.py --check # classe STALE_APPRECIATION
> ```

---

Expand All @@ -24,7 +36,7 @@ Cocher la portée effectivement couverte par la PR de revue (cf registre §3.2)
- [ ] **correctness** — corrections de bugs d'implémentation (off-by-one, edge case)
- [ ] **full** — toutes dimensions ci-dessus

> **Note promote** : tous les scopes ci-dessus promeuvent vers `AUTHOR_REVIEWED` si le reviewer == last_validator, ou `PEER_REVIEWED` si le reviewer ≠ last_validator (cf `classify_scientific_review` l.802-808).
> **La portée n'est plus ce qui promeut** (#14831). Elle dit *ce que la revue a couvert* ; l'appréciation, elle, se déclare explicitement au verdict ci-dessous. Faire dépendre la grade de la portée ou de l'identité du relecteur mesurait la provenance de la relecture, pas le risque du contenu.

## Constats

Expand All @@ -34,11 +46,53 @@ Liste des findings significatifs (1 ligne chacun) :
2. `<constat 2>`
3. ...

## Verdict
## Verdict — l'appréciation de confiance

- [ ] **PROMOTE_AUTHOR** — la revue justifie `scientific_reviewed_by = "<reviewer>"` et promeut `UNREVIEWED → AUTHOR_REVIEWED`
- [ ] **PROMOTE_PEER** — la revue est par un tiers distinct, promeut `UNREVIEWED → PEER_REVIEWED`
- [ ] **DEFER** — la revue nécessite une seconde passe
**Une seule case, et elle demande un argument écrit.** La question n'est pas « qui a
relu ? » mais **« quel risque ce notebook prend-il sur ce qu'il affirme ? »**.

- [ ] **ESTABLISHED** — contenu communément admis et universellement pratiqué. Le
notebook n'avance rien qui puisse être contesté par un lecteur compétent.
- [ ] **ADVANCED** — protocoles plus avancés, exécutions moins contrôlées, théories
récentes, interprétations discutables. Le contenu tient, mais il **engage**.
- [ ] **RESEARCH** — recherche active. Le contenu est explicitement en cours
d'élaboration, et le dire est la seule position honnête.
- [ ] **DEFER** — la revue nécessite une seconde passe. L'entrée n'est pas écrite au
registre, et le notebook reste `UNASSESSED` : **l'absence de jugement n'est pas
un mauvais score**, c'est le défaut honnête.

**Justification (obligatoire, 2–5 lignes)** — ce qui fait pencher vers cette classe
plutôt que vers la voisine. Nommer le point le plus contestable du notebook et dire
pourquoi il tombe de ce côté :

```
<justification>
```

> **Ne pas confondre avec `PRODUCTION`.** Cette carte n'accorde aucun passage en
> production. `PRODUCTION` est le tampon du responsable pédagogique — il dit que le
> notebook est finalisé pour être utilisé en cours **par d'autres** — et il vit dans
> [production-scope.md](production-scope.md). L'appréciation scientifique en est une
> condition **nécessaire, jamais suffisante**.

## Ancre de péremption (obligatoire)

Sans ancre, l'appréciation est **immortelle par omission** : elle ne se périmera jamais,
quel que soit le code qui passera ensuite. Le validateur le signale
(`WARN_NO_CODE_ANCHOR`).

```bash
python - <<'EOF'
import json, sys
sys.path.insert(0, "scripts/notebook_tools")
from generate_catalog import code_source_sha
print(code_source_sha(json.load(open("MyIA.AI.Notebooks/<chemin>.ipynb", encoding="utf-8"))))
EOF
```

- **`reviewed_code_sha`** : `<sortie de la commande ci-dessus>`
- **Vérifié contre** : `git rev-parse HEAD` = `<sha>` — l'arbre sur lequel la revue a
porté. Une revue menée sur une branche mesure autre chose que `main`.

## Preuves (G.1 obligatoires)

Expand All @@ -54,10 +108,12 @@ Liste des findings significatifs (1 ligne chacun) :

## Signature du reviewer

- **Reviewer** : `<login GitHub ou email>` (DOIT permettre `AUTHOR_REVIEWED` si == last_validator, ou `PEER_REVIEWED` si ≠)
- **Reviewer** : `<login GitHub ou email>` — rendu comme **preuve à côté** ; depuis #14831 il ne pilote plus la grade, donc une auto-revue n'est plus disqualifiante, elle est simplement *visible*
- **Date de revue** : `<YYYY-MM-DD>` (ISO 8601)
- **Notes** : `<libre, max 200 chars>`

---

**Note** : ce registre est volontairement plus restrictif que `EDITORIAL_REVIEW_CARD.md` — il exige une preuve de fond technique (algo/proba/demo/correctness), pas seulement pédagogique.

**Et il ne se clôt jamais.** Une carte remplie vaut pour l'état du code qu'elle ancre, pas pour le notebook à perpétuité. C'est la différence entre un audit ponctuel — qui vieillit en silence — et un régime permanent, qui se redéclare lui-même à chaque fois que le calcul change.
2 changes: 1 addition & 1 deletion docs/notebook-metadata/production-scope.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Le détail par notebook suit en strate A ci-dessous : consultation, plus décisi
| GenAI Image — Foundation | EPF GenAI Bachelor 3A | `01-1-OpenAI-DALL-E-3.ipynb` | 5 | |
| GenAI Audio — Foundation | EPF GenAI Bachelor 3A | `01-1-OpenAI-TTS-Intro.ipynb` | 5 | |
| GenAI Video — Foundation | EPF GenAI Bachelor 3A | `01-1-Video-Operations-Basics.ipynb` | 5 | |
| GenAI Texte (1-8) | EPF GenAI Bachelor 3A | `1_OpenAI_Intro.ipynb` | 8 | |
| GenAI Texte (1-8) | EPF GenAI Bachelor 3A | `01_OpenAI_Intro.ipynb` | 8 | |
| Search — Part 1 Foundations | EPITA Programmation par Contraintes | `Search-01-StateSpace.ipynb` | 13 | |
| Search — Part 2 CSP | EPITA Programmation par Contraintes | `CSP-1-Fundamentals.ipynb` | 9 | |
| Argument Analysis | EPITA IA Symbolique | `Argument_Analysis_Toulmin_Model.ipynb` | 4 | |
Expand Down
Loading
Loading