diff --git a/app/but/jury_but.py b/app/but/jury_but.py
index 41c081191b78337f365b7e43d9893ec09caccaf5..0a7779f2af83f3d01e87d2d54cb9e49e26cb847a 100644
--- a/app/but/jury_but.py
+++ b/app/but/jury_but.py
@@ -380,14 +380,24 @@ class DecisionsProposeesAnnee(DecisionsProposees):
                 sco_codes.ADJ,
             ] + self.codes
             explanation += f" et {self.nb_rcues_under_8} < 8"
-        else:
-            self.codes = [
-                sco_codes.RED,
-                sco_codes.NAR,
-                sco_codes.PAS1NCI,
-                sco_codes.ADJ,
-                sco_codes.PASD,  # voir #488 (discutable, conventions locales)
-            ] + self.codes
+        else:  # autres cas: non admis, non passage, non dem, pas la moitié des rcue:
+            if formsemestre.semestre_id % 2 and self.formsemestre_pair is None:
+                # Si jury sur un seul semestre impair, ne  propose pas redoublement
+                # et efface décision éventuellement existante
+                codes = [None]
+            else:
+                codes = []
+            self.codes = (
+                codes
+                + [
+                    sco_codes.RED,
+                    sco_codes.NAR,
+                    sco_codes.PAS1NCI,
+                    sco_codes.ADJ,
+                    sco_codes.PASD,  # voir #488 (discutable, conventions locales)
+                ]
+                + self.codes
+            )
             explanation += f""" et {self.nb_rcues_under_8
                                     } niveau{'x' if self.nb_rcues_under_8 > 1 else ''} < 8"""
 
@@ -514,7 +524,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
         """Les deux formsemestres auquel est inscrit l'étudiant (ni DEM ni DEF)
         du niveau auquel appartient formsemestre.
 
-        -> S_impair, S_pair
+        -> S_impair, S_pair (de la même année scolaire)
 
         Si l'origine est impair, S_impair est l'origine et S_pair est None
         Si l'origine est paire, S_pair est l'origine, et S_impair l'antérieur
@@ -524,9 +534,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
             return None, None
 
         if formsemestre.semestre_id % 2:
-            idx_autre = formsemestre.semestre_id + 1
+            idx_autre = formsemestre.semestre_id + 1  # impair, autre = suivant
         else:
-            idx_autre = formsemestre.semestre_id - 1
+            idx_autre = formsemestre.semestre_id - 1  # pair: autre = précédent
 
         # Cherche l'autre semestre de la même année scolaire:
         autre_formsemestre = None
@@ -610,6 +620,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
     def next_semestre_ids(self, code: str) -> set[int]:
         """Les indices des semestres dans lequels l'étudiant est autorisé
         à poursuivre après le semestre courant.
+        code: code jury sur année BUT
         """
         # La poursuite d'études dans un semestre pair d'une même année
         # est de droit pour tout étudiant.
@@ -653,6 +664,8 @@ class DecisionsProposeesAnnee(DecisionsProposees):
 
         Si les code_rcue et le code_annee ne sont pas fournis,
         et qu'il n'y en a pas déjà, enregistre ceux par défaut.
+
+        Si le code_annee est None, efface le code déjà enregistré.
         """
         log("jury_but.DecisionsProposeesAnnee.record_form")
         code_annee = self.codes[0]  # si pas dans le form, valeur par defaut
@@ -697,6 +710,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
     def record(self, code: str, mark_recorded: bool = True) -> bool:
         """Enregistre le code de l'année, et au besoin l'autorisation d'inscription.
         Si l'étudiant est DEM ou DEF, ne fait rien.
+        Si le code est None, efface le code déjà enregistré.
         Si mark_recorded est vrai, positionne self.recorded
         """
         if self.inscription_etat != scu.INSCRIT:
@@ -746,7 +760,9 @@ class DecisionsProposeesAnnee(DecisionsProposees):
         return True
 
     def record_autorisation_inscription(self, code: str):
-        """Autorisation d'inscription dans semestre suivant"""
+        """Autorisation d'inscription dans semestre suivant.
+        code: code jury sur année BUT
+        """
         if self.autorisations_recorded:
             return
         if self.inscription_etat != scu.INSCRIT:
diff --git a/sco_version.py b/sco_version.py
index 8bf52bab796bb82adccf9853fc2d4a4017f27bf7..26ebd6f767db68472f3330b81ce1ffb36150c193 100644
--- a/sco_version.py
+++ b/sco_version.py
@@ -1,7 +1,7 @@
 # -*- mode: python -*-
 # -*- coding: utf-8 -*-
 
-SCOVERSION = "9.6.83"
+SCOVERSION = "9.6.84"
 
 SCONAME = "ScoDoc"
 
diff --git a/tests/ressources/yaml/cursus_but_geii_lyon.yaml b/tests/ressources/yaml/cursus_but_geii_lyon.yaml
index fefdc9b6bd3bd4a31acbd8c450affab984cd82c3..727e818fb64c38c8a4579f84e4727b448bed6a56 100644
--- a/tests/ressources/yaml/cursus_but_geii_lyon.yaml
+++ b/tests/ressources/yaml/cursus_but_geii_lyon.yaml
@@ -2,7 +2,7 @@
 # Essais avec un BUT GEII, 2 UE en BUT1 / 4 UE en BUT2-BUT3 et 3 parcours
 # Contrib Pascal B.
 #   Voir tests/unit/test_but_jury.py
-#    pytest --pdb -m lyon tests/unit/test_but_jury.py
+#    pytest -x --pdb -m lyon tests/unit/test_but_jury.py
 
 
 ReferentielCompetences:
@@ -372,18 +372,18 @@ Etudiants:
                 moy_ue: 9.5 # moyenne non capitalisée ici
                 moy_ue_with_cap: 12.76
 # Pas de décisions RCUE
-#               "UE11":  -- non applicable 
-#                 code_valide: ADM  -- non applicable 
-#                 decision_jury: ADM  -- non applicable 
-#                 rcue:  -- non applicable 
-#                   moy_rcue: 10.94  -- non applicable 
-#                   est_compensable: False  -- non applicable 
-#               "UE12":  -- non applicable 
-#                 code_valide: ADM -- non applicable 
-#                 decision_jury: ADM  -- non applicable 
-#                 rcue:  -- non applicable 
-#                   moy_rcue: 10.94  -- non applicable 
-#                   est_compensable: False  -- non applicable 
+#               "UE11":  -- non applicable
+#                 code_valide: ADM  -- non applicable
+#                 decision_jury: ADM  -- non applicable
+#                 rcue:  -- non applicable
+#                   moy_rcue: 10.94  -- non applicable
+#                   est_compensable: False  -- non applicable
+#               "UE12":  -- non applicable
+#                 code_valide: ADM -- non applicable
+#                 decision_jury: ADM  -- non applicable
+#                 rcue:  -- non applicable
+#                   moy_rcue: 10.94  -- non applicable
+#                   est_compensable: False  -- non applicable
           decision_annee: AJ
 # Nouveaux cas RED (mardi 17/01/2023)
   geii8bis:
@@ -717,7 +717,7 @@ Etudiants:
                 code_valide: ADM
                 moy_ue: 12.0000
               "UE12":
-                code_valide: AJ  
+                code_valide: AJ
           # PAS DE RCUE car UE12 capitalisée mailleure qu'actuelle
           decision_annee: AJ
   geii20:
@@ -1407,3 +1407,25 @@ Etudiants:
         notes_modules: # combinaison pour avoir ADM ADM ADM AJ
           "PF4": 12
           "SAE4AII": 8
+  # Test code annuel après un seul semestre
+  geiiS10:
+    prenom: "etugeiiS100 un semestre"
+    civilite: M
+    formsemestres:
+      S1:
+        notes_modules: # on joue avec les SAE seulement car elles sont "diagonales"
+          "S1.1": 18.0000
+          "S1.2": 19.0000
+        attendu: # les codes jury que l'on doit vérifier
+          deca:
+            passage_de_droit: False
+            code_valide: "" # le code "annuel" BUT proposé en auto: aucun
+            nb_competences: 2
+            nb_rcue_annee: 0
+            decisions_ues:
+                "UE11":
+                  code_valide: ADM
+                  moy_ue: 18.0000
+                "UE12":
+                  code_valide: ADM
+                  moy_ue: 19.0000
diff --git a/tests/unit/yaml_setup_but.py b/tests/unit/yaml_setup_but.py
index a0bbff8eabbea62aeb9798d69ade5072c9eda734..c4ab421d473c53e38f206d9f1fe5981e0189b432 100644
--- a/tests/unit/yaml_setup_but.py
+++ b/tests/unit/yaml_setup_but.py
@@ -242,7 +242,9 @@ def but_compare_decisions_annee(deca: DecisionsProposeesAnnee, deca_att: dict):
 
     for attr in ("passage_de_droit", "code_valide", "nb_competences"):
         if attr in deca_att:
-            assert getattr(deca, attr) == deca_att[attr]
+            assert getattr(deca, attr) == (
+                deca_att[attr] if deca_att[attr] != "" else None
+            )
 
     if "decisions_ues" in deca_att:
         but_check_decisions_ues(deca.decisions_ues, deca_att["decisions_ues"])