Commit graph

1372 commits

Author SHA1 Message Date
b8361c30e6 [FIX] git remote : ignorer un dépôt fautif, lister les écarts à la fin
Un répertoire vidé à la main passe `os.path.isdir` puis fait lever
l'ouverture du dépôt, ce qui emportait tout le reste du lot. Ces états —
clone interrompu, `.git` effacé — sont courants sur un checkout de
développement, et sans rapport avec les dépôts qui attendent leur remote.
Les écarts sont rendus plutôt qu'affichés au fil de l'eau : noyés dans la
trace d'un lot de plus de cent dépôts, ils ne se voient plus. La sortie
reste nulle, comme déjà pour un répertoire absent.
Vérifié dans des dépôts jetables ; 6 tests neufs, dont 2 échouent si le
garde-fou est retiré.

--- EN ---

A directory emptied by hand passes `os.path.isdir` then makes opening the
repository raise, which took down the whole rest of the batch. Such states —
an interrupted clone, a deleted `.git` — are common on a development
checkout, and unrelated to the repositories awaiting their remote.
Deviations are returned rather than printed as they happen: drowned in the
trace of a batch of over a hundred repositories, they can no longer be seen.
The exit code stays zero, as it already was for a missing directory.
Checked in throwaway repositories; 6 new tests, 2 of which fail if the guard
is removed.

Assisted-by: Claude Opus 5
2026-09-04 03:48:39 +00:00
a60baf743e [FIX] commit msg : chercher lib_identifiant sans masquer GitPython
Le répertoire ajouté est `script/`, qui porte un `git/` : en tête de
`sys.path`, il fait résoudre `import git` vers ce paquet plutôt que vers
GitPython, pour tout module importé ENSUITE dans le même processus — une
bibliothèque tierce disparaît parce qu'une des nôtres porte le même nom.
En queue, `lib_identifiant` se trouve toujours et les paquets installés
gardent la priorité ; la racine du dépôt suit la même règle, elle porte un
`test/` homonyme d'un paquet standard.
Mesuré : `unittest discover -p 'test_git*.py'` passe de 49 tests et une
erreur d'import à 84 verts ; le hook commit-msg reste vérifié.

--- EN ---

The directory being added is `script/`, which holds a `git/`: at the head of
`sys.path` it makes `import git` resolve to that package rather than to
GitPython, for every module imported AFTERWARDS in the same process — a
third-party library vanishes because one of ours bears the same name.
At the tail, `lib_identifiant` is still found and installed packages keep
their precedence; the repository root follows the same rule, it holds a
`test/` sharing its name with a standard library package.
Measured: `unittest discover -p 'test_git*.py'` goes from 49 tests and one
import error to 84 green; the commit-msg hook stays verified.

Assisted-by: Claude Opus 5
2026-09-04 03:48:36 +00:00
eb5d6a72a0 [FIX] git tool : garder le dépôt racine quand le manifeste manque
Le traitement de `add_root` est en FIN de fonction, et deux retours
anticipés lui sautaient par-dessus : sans manifeste, la liste revenait vide
alors que la racine était demandée. Le script qui réécrit les remotes ne
trouvait donc rien à faire sur un checkout sans `.repo`, et l'annonçait
comme un succès.
L'ajout de la racine et le tri passent par un point de sortie unique, ce
qui supprime la copie qui gardait le défaut dans une variante sur deux. Une
origine absente vaut l'URL par défaut plutôt qu'une exception.
Vérifié dans un dépôt jetable, dans les deux sens et sans origine ; 4 tests
neufs, qui échouent si le retour anticipé revient.

--- EN ---

The `add_root` handling sits at the END of the function, and two early
returns jumped over it: with no manifest, the list came back empty although
the root had been asked for. The script that rewrites the remotes therefore
found nothing to do on a checkout without `.repo`, and reported it as a
success.
Adding the root and sorting now go through a single exit point, which drops
the copy that kept the fault in one variant out of two. A missing origin
falls back to the default URL rather than raising.
Checked in a throwaway repository, both ways and with no origin; 4 new
tests, which fail if the early return comes back.

Assisted-by: Claude Opus 5
2026-09-04 03:48:32 +00:00
2fba0d6871 Merge branch 'todo_vpn_client'
[ADD] vpn : cinq tunnels au menu, secrets en coffre, diagnostic étagé

7 commits. Rien ne permettait de monter un tunnel VPN, ni de dire pourquoi il
refuse de monter. Cinq technologies libres arrivent au menu ; le profil,
lisible et partageable, est séparé des secrets, qui vivent dans un coffre
KeePassXC et ne touchent jamais un disque persistant. Le diagnostic part du
noyau et remonte, pour que la première ligne fausse soit la cause et non une
conséquence, et propose le remède connu sans l'appliquer seul. Demander tout
le trafic par le tunnel ne coupe plus la session SSH qui en donne l'ordre, et
le coffre s'ouvre sur une machine sans tkinter, donc sur tout serveur.
Vérifié : 175 tests VPN et 8 sur le coffre ; le moteur, sorti seul dans un
worktree, y passe ses 144 tests sans le menu.

--- EN ---

7 commits. Nothing could raise a VPN tunnel, nor say why one refuses to come
up. Five free technologies arrive at the menu; the profile, readable and
shareable, is kept apart from the secrets, which live in a KeePassXC vault
and never touch a persistent disk. Diagnosis starts at the kernel and climbs,
so the first false line is the cause and not a consequence, and offers the
known remedy without applying it alone. Asking for all traffic through the
tunnel no longer cuts the SSH session giving the order, and the vault opens
on a machine without tkinter, which is every server.
Checked: 175 VPN tests and 8 on the vault; the engine, checked out alone in a
worktree, passes its 144 tests there without the menu.

Assisted-by: Claude Opus 5
2026-09-04 03:47:43 +00:00
2d66dda129 [UPD] changelog : l'outil VPN, son diagnostic, le coffre sur un serveur
La branche part de master : elle livre l'outil entier, pas des retouches.
Deux puces sous Ajouté — l'outil et son diagnostic étagé — et une sous
Corrigé pour le coffre KeePassXC, qui ne doit rien au VPN et servait déjà
ailleurs.

Ce qu'une branche corrige de son propre travail n'y figure pas : le lanceur
de tests et ses huit fichiers muets sont revenus à l'état de master, et une
puce les annonçant décrirait un aller-retour invisible du dehors.

--- EN ---

The branch forks from master: it delivers the whole tool, not touch-ups. Two
bullets under Added — the tool and its staged diagnosis — and one under Fixed
for the KeePassXC vault, which owes nothing to the VPN and already served
elsewhere.

What a branch fixes in its own work is absent: the test launcher and its
eight silent files are back to master's state, and a bullet announcing them
would describe a round trip invisible from outside.

Assisted-by: Claude Opus 5
2026-09-04 03:43:11 +00:00
315e45e5f0 [ADD] menu vpn : créer un profil, déposer les secrets, monter le tunnel
`vpn.py` savait tout faire en ligne de commande, mais il fallait écrire le
profil JSON à la main et déposer les secrets dans KeePassXC soi-même. Le menu
pose les questions que le pilote choisi déclare, et lui seul : ajouter une
technologie n'ajoute pas une ligne ici.

Le coffre est manipulé EN PROCESSUS — le mot de passe maître est déjà en
mémoire, le redemander à un sous-processus serait une saisie de plus à chaque
geste. Montage, démontage et diagnostic passent au contraire par `vpn.py` en
sous-processus : ils durent, ils parlent, et la sortie en direct est ce qui
rend une montée de tunnel suivable.
Vérifié : 37 tests sur le menu, aucune saisie réelle.

--- EN ---

`vpn.py` could already do everything from the command line, but the JSON
profile had to be written by hand and the secrets filed into KeePassXC by
hand. The menu asks the questions the chosen driver declares, and only those:
adding a technology adds no line here.

The vault is handled IN PROCESS — the master password is already in memory,
and asking a subprocess for it again would be one more entry at every step.
Raising, tearing down and diagnosing go through `vpn.py` as a subprocess
instead: they last, they talk, and live output is what makes a tunnel coming
up followable.
Checked: 37 tests on the menu, no real input.

Assisted-by: Claude Opus 5
2026-09-04 03:43:02 +00:00
197d19d61e [ADD] vpn : cinq pilotes, secrets en coffre, diagnostic étagé
Le dépôt n'avait aucun moyen de monter un tunnel VPN ni de dire pourquoi il
refuse de monter. Cinq technologies libres, un pilote chacune, derrière un
`vpn.py` qui monte, démonte et diagnostique.

Ce qui n'est pas secret — hôte, utilisateur, routes, MTU — vit dans une
configuration JSON lisible ; clés pré-partagées et mots de passe vivent dans
un coffre KeePassXC. Un profil se montre et se partage sans donner de quoi
monter le tunnel. Les secrets s'écrivent en tmpfs sous 0700, jamais sur un
disque persistant. Le diagnostic part du noyau et remonte, pour que la
première ligne fausse soit la cause et non une conséquence.
Vérifié : 138 tests, dont le rendu de chaque fichier généré.

--- EN ---

The repository had no way to raise a VPN tunnel, nor to say why one refuses
to come up. Five free technologies, one driver each, behind a `vpn.py` that
raises, tears down and diagnoses.

What is not secret — host, user, routes, MTU — lives in readable JSON
configuration; pre-shared keys and passwords live in a KeePassXC vault. A
profile can be shown and shared without handing over the means to raise the
tunnel. Secrets are written to tmpfs at 0700, never to a persistent disk.
Diagnosis starts at the kernel and climbs, so the first false line is the
cause and not a consequence.
Checked: 138 tests, including the rendering of every generated file.

Assisted-by: Claude Opus 5
2026-09-04 03:42:49 +00:00
8181e693a2 [REF] tests : passer isort et black sur trois fichiers oubliés
Trois fichiers de la suite n'étaient pas au format du dépôt : imports non
triés, expressions coupées là où la ligne tient. `make format` les rattrape.
Aucun test n'est ajouté, retiré ni modifié dans ce qu'il vérifie.

--- EN ---

Three files of the suite were not in the repository's format: unsorted
imports, expressions broken where the line fits. `make format` catches them
up. No test is added, removed, or changed in what it checks.

Assisted-by: Claude Opus 5
2026-09-04 03:42:34 +00:00
bdc0e19302 [UPD] tests : nommer le répertoire comme frontière de la suite
Le lanceur prend TOUT `test/test_*.py` par glob, et l'en-tête disait
pourquoi : une liste de préfixes oublie ce qu'on ajoute. Il ne disait pas où
mettre ce qui doit rester dehors, si bien qu'une famille de tests nouvelle
semblait avoir quelque chose à déclarer ici.

La frontière est un RÉPERTOIRE : ce qui ne doit pas être lancé vit ailleurs
que dans `test/`. Rien à déclarer, donc rien à oublier de déclarer.

--- EN ---

The launcher takes ALL of `test/test_*.py` by glob, and the header said why:
a list of prefixes forgets whatever gets added. It did not say where to put
what must stay out, so a new family of tests looked as though it had
something to declare here.

The boundary is a DIRECTORY: what must not run lives somewhere other than
`test/`. Nothing to declare, hence nothing to forget to declare.

Assisted-by: Claude Opus 5
2026-09-04 03:42:27 +00:00
ae9463ebcb [FIX] kdbx : nommer le coffre avant que getpass ne pose sa question
L'invite de `getpass` part vers le terminal, la ligne qui nomme le coffre
vers la sortie standard — un TUBE dès qu'un menu nous lance. Sans vidage, les
deux ressortaient dans le désordre : « Mot de passe du coffre : Coffre
KeePass : <chemin> », la question avant ce dont elle parle.

Le bouchon de `print` des tests accepte désormais la signature complète de
`print` : sans `**k`, ajouter un `flush` au code testé faisait échouer six
tests sur une différence étrangère à ce qu'ils vérifient.

--- EN ---

The `getpass` prompt goes to the terminal, the line naming the vault to
standard output — a PIPE as soon as a menu launches us. Without a flush the
two came out in the wrong order: "Vault password: KeePass vault: <path>", the
question before what it is about.

The tests' `print` stub now accepts the full signature of `print`: without
`**k`, adding a `flush` to the code under test failed six tests over a
difference foreign to what they check.

Assisted-by: Claude Opus 5
2026-09-04 03:42:18 +00:00
cedf702226 [FIX] kdbx : ouvrir le coffre sans tkinter, donc sur un serveur
Sur une machine sans tkinter — tout serveur — `get_kdbx()` rendait None en
journalisant « pykeepass is not installed », alors que pykeepass était là.
Les deux imports partageaient un seul `try` : l'absence de tkinter mettait
aussi `PyKeePass` à None, et le coffre restait inouvrable même avec chemin et
mot de passe configurés.

tkinter ne sert qu'au sélecteur de fichier, quand aucun chemin n'est
configuré ; deux blocs séparés le rendent à ce seul rôle.

--- EN ---

On a machine without tkinter — every server — `get_kdbx()` returned None
while logging "pykeepass is not installed", though pykeepass was present.
Both imports shared one `try`: a missing tkinter set `PyKeePass` to None as
well, and the vault stayed unopenable even with path and password configured.

tkinter serves only the file picker, when no path is configured; two separate
blocks give it back that single role.

Assisted-by: Claude Opus 5
2026-09-04 03:42:00 +00:00
890cd3944f Merge branch 'develop_qemu_3D'
[ADD] qemu et todo : 3D, diagnostic, récupération, outils installés

42 commits. La 3D des VM QEMU devient utilisable de bout en bout : quatre
pannes la rendaient inopérante en silence, dont un attribut de libvirt
12.5.0 qui l'emporte sur « accel3d » et un groupe manquant dans l'invité
qui renvoyait toute application GL au rendu logiciel. Un diagnostic en
lecture seule, écrit dans un fichier à transmettre, dit ce que l'hôte
sait faire ET ce que chaque VM recevra. Viennent avec : récupération de
fichiers dans un disque mort, assistants posés dans l'invité, menu qui
installe, libvirt par le groupe et non par sudo. 1 202 tests lancés.

--- EN ---

42 commits. 3D on QEMU VMs becomes usable end to end: four faults left it
silently inert, among them an attribute from libvirt 12.5.0 that outranks
« accel3d » and a group missing in the guest that sent every GL
application back to software rendering. A read-only diagnostic, written
to one file to hand over, now says what the host can do AND what each VM
will get. Along with it: file recovery from a dead disk, assistants
installed in the guest, a menu that installs, and libvirt reached through
the group rather than sudo. 1,202 tests run.

Assisted-by: Claude Opus 5
2026-09-03 05:01:27 -04:00
86c4576f01 [IMP] script todo : icônes des cinq commandes du menu Claude
Le menu qui déploie les commandes d'assistant était le dernier resté nu,
et cinq lignes qui ouvrent toutes sur le même mot se lisent une par une.
Chaque signe dit ce que la commande fait — message, fusion, plan, code,
inventaire — plutôt que de répéter qu'il s'agit d'une commande.

Les cinq emoji rendent sur deux colonnes, d'où l'espace unique qui les
sépare du libellé. Aucun ne servait ailleurs : un même signe pour deux
concepts distincts se lit comme un lien qui n'existe pas.

--- EN ---

The menu deploying assistant commands was the last one left bare, and
five lines all opening on the same word are read one by one. Each sign
says what the command does — message, merge, plan, code, inventory —
instead of repeating that it is a command.

The five emoji render two columns wide, hence the single space before
the label. None was in use elsewhere: one sign for two distinct concepts
reads as a link that does not exist.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
7ce14e2929 [UPD] changelog : la branche qemu 3D, diagnostic et outils 2026-09-03 05:00:55 -04:00
68eff72243 [ADD] qemu deploy : poser rtk, starship et un agent dans la VM
Une case de plus au catalogue des outils, donc une case dans les deux
écrans sans y toucher. Cochée, elle découvre le choix de l'agent — Claude
Code ou opencode — et l'identité git, pré-remplie avec celle de l'hôte :
c'est ce que la VM reçoit déjà, et un champ vide la ferait croire absente.
Ce qui est saisi prime, champ par champ.

Phase « before », où chaque outil se garde lui-même. Chaque pose est aussi
privée d'entrée standard et bornée dans le temps : « || true » couvre
l'échec, pas l'ATTENTE, et un installateur amont qui pose une question
resterait pendu sur un SSH sans terminal — d'où « -y » pour starship.

--- EN ---

One more entry in the tool catalogue, hence one more box on both screens
for free. Ticked, it reveals the agent choice — Claude Code or opencode —
and the git identity, prefilled from the host: that is what the VM
already gets, and an empty field would suggest none. What is typed wins,
field by field.

Phase « before », where each tool guards itself. Every install is also
denied stdin and time-bounded: « || true » covers failure, not WAITING,
and an upstream installer asking a question would hang on a terminal-less
SSH — hence « -y » for starship.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
988ea6bcd5 [REF] todo shell : une table unique pour les installateurs amont
Les mêmes outils se posent à DEUX endroits : sur l'hôte par le menu Shell,
et bientôt dans une VM par le déploiement QEMU. Une URL amont recopiée
dérive dès que l'une des deux copies change, et c'est la seconde qu'on
oublie — celle qui n'a pas de menu pour la montrer.

Les noms de classe restent : ils sont l'interface, et les tests les
interrogent. Aucun comportement ne change.

--- EN ---

The same tools are installed in TWO places: on the host from the Shell
menu, and soon inside a VM from the QEMU deployment. A copied upstream
URL drifts as soon as one of the two copies changes, and the forgotten
one is the second — the one with no menu to show it.

The class names stay: they are the interface, and the tests read them.
No behaviour changes.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
43446c4ba9 [FIX] tests qemu : deux gardes rendus muets par mes propres ajouts
Le garde des menus refusait le menu QEMU : deux entrées y étaient arrivées
sans être déclarées dans sa table, donc sans que personne dise où elles
mènent. C'est la panne qu'il existe pour signaler, et elle traînait rouge.

Le garde de la suite refusait test_qemu_start_egl : quatre classes s'y
étaient empilées APRÈS « unittest.main() ». Elles tournaient — unittest
collecte à l'import — mais le fichier n'était plus lançable seul, ce que
le garde vérifie précisément.

--- EN ---

The menu guard rejected the QEMU menu: two entries had landed there
undeclared in its table, so with nobody saying where they lead. That is
the very failure it exists to report, and it sat red.

The suite guard rejected test_qemu_start_egl: four classes had piled up
AFTER « unittest.main() ». They ran — unittest collects at import — but
the file was no longer runnable on its own, which is exactly what the
guard checks.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
b474b6d65e [FIX] qemu 3D : donner à l'invité l'accès au nœud de rendu
Le matériel virtuel accéléré ne suffisait pas. Dans l'invité, le nœud de
rendu appartient à « root:render » en 0660 et le compte créé n'y était
pas : toute application GL retombait sur le rendu logiciel alors que la
négociation VIRGL avait réussi, et rien ne le signalait. En session
graphique locale, logind pose une ACL pour l'utilisateur du siège ; en
SSH ou en tty, le cas d'une VM de ce parc, personne ne la pose.

Les groupes sont DÉCLARÉS avant d'être utilisés : « useradd -G » échoue
sur un nom inconnu, et cloud-init ne crée alors pas le compte du tout —
la VM démarre inaccessible. « render » manque des images anciennes. Même
parité côté preseed, par « groupadd -f ». « --gpu off » n'ajoute rien.

--- EN ---

Accelerated virtual hardware was not enough. In the guest the render
node is « root:render » at 0660 and the created account was not in it:
every GL application fell back to software rendering although VIRGL
negotiation had succeeded, with nothing to say so. On a local graphical
session logind sets an ACL for the seat's user; over SSH or on a tty,
which is what these VMs get, nobody sets one.

Groups are DECLARED before use: « useradd -G » fails on an unknown name
and cloud-init then creates no account at all — the VM boots
unreachable. « render » is missing from older images. The preseed keeps
parity via « groupadd -f ». « --gpu off » adds nothing.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
612d943671 [ADD] qemu diagnostic : l'état 3D de chaque VM, ABI figée comprise
Le rapport disait ce que l'HÔTE sait faire, jamais ce que chaque VM
recevra au prochain démarrage. Trois valeurs y répondent ensemble et
aucune seule : le type de vidéo, « accel3d », et le device figé par
libvirt, qui l'emporte sur les deux autres. La section les lit dans la
définition persistante et écrit la commande qui défige, sans la lancer.

Les sections Python du rapport sont désormais isolées. Le fichier
s'écrit d'un bloc à la fin : une section qui lève emportait tout ce qui
avait été relevé avant elle, laissant sans rapport au moment d'en avoir
besoin. Le double de test rendait un objet sans « returncode », ce qui
masquait le défaut.

--- EN ---

The report said what the HOST can do, never what each VM will get on its
next boot. Three values answer that together and none alone: video type,
« accel3d », and the device libvirt pinned, which outranks both. The
section reads them from the persistent definition and writes out the
unpinning command without running it.

Python sections of the report are now isolated. The file is written in
one block at the end: a section that raised took down everything
gathered before it, leaving no report exactly when one is needed. The
test double returned an object with no « returncode », hiding the fault.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
1b26c4661b [FIX] qemu 3D : voir l'ABI figée qui annule l'accélération demandée
Depuis libvirt 12.5.0, le <model> vidéo porte un attribut « device » qui
grave le device QEMU retenu, pour tenir l'ABI de l'invité stable d'un
démarrage à l'autre. Il l'emporte sur « accel3d ». Une VM démarrée une
première fois sans 3D — module GL absent, ou option non cochée — garde
donc le device sans GL, et l'activer ensuite n'écrit qu'une intention :
QEMU reçoit toujours « virtio-vga » nu.

L'état lisait « accel3d » sans lire cet attribut, si bien que le résumé
annonçait « 3D » sur une VM qui tourne sans. Il porte désormais le device
figé quand celui-ci contredit la demande.

--- EN ---

Since libvirt 12.5.0 the video <model> carries a « device » attribute
recording the chosen QEMU device, to keep the guest ABI stable across
restarts. It outranks « accel3d ». A VM first started without 3D — GL
module absent, or the box unticked — therefore keeps the non-GL device,
and enabling it afterwards writes an intent only: QEMU still gets plain
« virtio-vga ».

State read « accel3d » without that attribute, so the summary announced
« 3D » on a VM running without it. It now names the pinned device
whenever it contradicts the request.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
94090d5280 [FIX] qemu 3D : le module virtio-vga-gl manquait au relevé des pièces
Les deux devices accélérés sont des modules séparés, empaquetés à part
sur les distributions qui découpent QEMU. Le relevé ne cherchait que
« virtio-gpu-gl » ; c'est « virtio-vga-gl » que libvirt exige pour un
écran principal compatible VGA, soit le cas d'une VM graphique. Le
rapport ressortait donc tout en vert à côté de la pièce absente.

Sans ce module, QEMU n'annonce pas le device, libvirt le remplace en
silence par « virtio-vga » nu et la VM démarre sans 3D — l'egl-headless
demandé restant en place, rien dans la définition ne trahit le repli.

--- EN ---

The two accelerated devices are separate modules, packaged apart on
distributions that split QEMU. The survey looked only for
« virtio-gpu-gl »; libvirt needs « virtio-vga-gl » for a VGA-compatible
primary display, which is what a graphical VM gets. The report therefore
came back all green next to the missing piece.

Without that module QEMU does not advertise the device, libvirt quietly
falls back to plain « virtio-vga » and the VM boots with no 3D — the
requested egl-headless still in place, nothing in the definition telling.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
9370bff319 [ADD] qemu diagnostic : le device vidéo reçu par le QEMU en cours
Le relevé disait ce que la définition DEMANDE, jamais ce que la VM a
REÇU ; libvirt peut retirer l'accélération entre les deux sans le
signaler. Or « egl-headless » paraît sur la ligne de commande que la 3D
soit active ou non : le seul témoin est le suffixe « -gl » du device.
Chercher « virgl » n'aide pas — cette forme ne s'écrit plus sur les QEMU
récents, et son absence sur une VM accélérée fait conclure à un réglage
manquant qui n'existe pas.

La sonde lit /proc/<pid>/cmdline, sans privilège, et trie sur argv[0] :
sur la ligne entière elle se compterait elle-même.

--- EN ---

The report told what the definition ASKS for, never what the VM GOT;
libvirt can drop acceleration in between without saying so. And
« egl-headless » shows on the command line whether 3D is live or not:
the only witness is the device's « -gl » suffix. Grepping for « virgl »
does not help — that spelling is gone from recent QEMU, and its absence
on an accelerated VM suggests a missing setting that does not exist.

The probe reads /proc/<pid>/cmdline, unprivileged, and sorts on argv[0]:
on the whole line it would count itself.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
6f7ad39616 [IMP] script todo : icônes de menu, alignées sur leur largeur rendue
Le menu Git avait posé la convention ; dix autres restaient nus, et une
liste sans icône se lit ligne à ligne. L'espacement suit la largeur
RENDUE, lue dans Unicode et non devinée : deux espaces derrière un emoji
d'une colonne, une derrière un large — d'où le changement de signe de la
Configuration, dont le sien décalait le menu principal. Un même concept
garde son signe d'un menu à l'autre. « Quitter » garde sa traduction nue,
sa clé servant onze fois en raccourci de pied de page : son icône se pose
sur la ligne du menu.

Vérifié : menus rendus dans les deux langues, aucune clé incomplète,
aucune icône divergente entre les langues.

--- EN ---

The Git menu had set the convention; ten others stayed bare, and a list
without icons is read line by line. Spacing follows the RENDERED width,
read from Unicode rather than guessed: two spaces after a one-column
emoji, one after a wide one — hence the new sign for Configuration, whose
own offset the main menu. One concept keeps its sign from menu to menu.
« Quit » keeps its bare translation, its key serving eleven times as a
footer shortcut: its icon sits on the menu's own line.

Checked: menus rendered in both languages, no incomplete key, no icon
diverging between languages.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
625288fd4c [ADD] qemu diagnostic : un relevé à transmettre, Gérer scindé en trois
Un problème de VM se résout souvent par quelqu'un qui n'a pas accès à la
machine : vingt et une sondes en lecture écrivent un relevé unique —
hôte, hyperviseur, GPU, outils, stockage — chacune bornée dans le temps,
une commande qui pend ne devant pas retenir le rapport. Sur le pilote
NVIDIA propriétaire, trois conditions vivent hors des briques Mesa et
QEMU, dont la liste de périphériques où libvirt n'ajoute jamais les nœuds
de la carte : le relevé les nomme et propose la commande qui installe ce
qui lui manque, affichée avant la question. Gérer se scinde en trois.

--- EN ---

A VM problem is often solved by someone with no access to the machine:
twenty-one read-only probes write one report — host, hypervisor, GPU,
tools, storage — each time-bounded, since a command that hangs must not
hold the report. On the proprietary NVIDIA driver three conditions live
outside the Mesa and QEMU pieces, among them the device list where
libvirt never adds the card's own nodes: the report names them and offers
the command installing what it lacks, shown before the question is put.
The Manage menu splits in three.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
416ed42448 [ADD] qemu manage : retirer la 3D quand le démarrage échoue sur EGL
Le nœud de rendu peut exister sans qu'EGL y démarre : QEMU refuse alors
le domaine, et la 3D écrite dans la définition rend la VM inutilisable
jusqu'à ce que quelqu'un défasse le réglage. La création avait déjà son
repli, le réglage d'une VM existante n'en avait pas. Un relevé accompagne
le refus, car deux briques distinctes entrent en jeu : egl-headless ouvre
le nœud par GBM — c'est Mesa qui répond — et virglrenderer ne sert
qu'ensuite, donc l'installer ne répare pas un EGL qui refuse.

Vérifié : 11 tests, rougis par trois mutations — rattraper n'importe quel
échec, ne pas redémarrer après le retrait, éteindre l'autostart au passage.

--- EN ---

The render node can exist without EGL starting on it: QEMU then refuses
the domain, and the 3D written into the definition leaves the VM unusable
until someone undoes the setting. Creation already had its fallback,
adjusting an existing VM had none. A report comes with the refusal, since
two distinct bricks are involved: egl-headless opens the node through GBM
— Mesa answers — and virglrenderer only serves afterwards, so installing
it repairs no EGL that refuses.

Checked: 11 tests, turned red by three mutations — catching any failure,
not restarting after removal, switching autostart off along the way.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
83c0d705c1 [FIX] qemu stats : un « datetime » de trop faisait tomber le menu
Le module importe la CLASSE datetime, pas le module : « datetime.datetime »
n'existe donc pas, et l'écran des statistiques sortait sur une
AttributeError qui emportait TODO entier. La garde couvre aussi
TypeError : un horodatage absent vaut None dans un résumé sans aucune
installation, et une statistique ne doit pas décider de la survie du menu.

Vérifié : un horodatage valide rend sa date, None et une valeur hors
bornes rendent « ? » sans lever.

--- EN ---

The module imports the datetime CLASS, not the module: « datetime.datetime »
therefore does not exist, and the statistics screen exited on an
AttributeError that took the whole of TODO with it. The guard also covers
TypeError: an absent timestamp is None in a summary with no install at
all, and a statistic must not decide whether the menu survives.

Checked: a valid timestamp renders its date, None and an out-of-range
value render « ? » without raising.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
12cef44991 [FIX] qemu menu : sortir le venv du PATH des outils système
Le « bin » du venv est en tête du PATH de chaque commande lancée par le
menu, et il contient un python3. Un outil système écrit en Python et
amorcé par « env python3 » s'y amorce donc, dans un interpréteur où les
modules de la distribution n'existent pas : l'import échoue sur un module
que la machine possède pourtant. Sous sudo le piège était invisible, sudo
réinitialisant le PATH ; le retirer là où il ne servait plus l'a mis au
jour.

Vérifié : 6 tests, rougis par trois mutations. La ligne d'amorçage des
outils visés n'a pas été inspectée : le mécanisme est démontré, pas qu'il
soit la cause sur un hôte donné.

--- EN ---

The venv's « bin » leads the PATH of every command the menu launches, and
it holds a python3. A system tool written in Python and started through
« env python3 » therefore boots on that interpreter, where the
distribution's modules do not exist: the import fails on a module the
machine does have. Under sudo the trap was invisible, sudo resetting the
PATH; removing it where it was no longer needed brought it out.

Checked: 6 tests, turned red by three mutations. The shebang of the tools
concerned was not inspected: the mechanism is demonstrated, not that it
is the cause on any given host.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
f016eefce9 [ADD] qemu menu : récupérer des fichiers dans le disque d'une VM
Une VM qui ne démarre plus garde ses fichiers : libguestfs monte son
qcow2 sans elle. Toute commande porte « --ro », et c'est ce qui change la
manœuvre : ouvrir en écriture le disque d'une machine allumée corrompt
son système de fichiers, la lire ne risque rien. Un arrêt reste proposé
et non imposé — une lecture vivante voit un état peut-être incohérent,
un fichier à moitié écrit, un journal non rejoué. Le nom du paquet suit
la distribution, celui de Debian n'existant nulle part ailleurs.

Vérifié : 16 tests, rougis par quatre mutations — perdre le « --ro »,
donner le nom Debian partout, dupliquer un numéro, retirer l'entrée.

--- EN ---

A VM that no longer boots still holds its files: libguestfs mounts its
qcow2 without it. Every command carries « --ro », and that is what
changes the operation: opening a running machine's disk for writing
corrupts its filesystem, reading it risks nothing. A shutdown stays
offered, not imposed — a live read sees a possibly torn state, a
half-written file, an unreplayed journal. The package name follows the
distribution, Debian's existing nowhere else.

Checked: 16 tests, turned red by four mutations — losing « --ro », using
Debian's name everywhere, duplicating a number, dropping the entry.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
bf114ac182 [FIX] script todo : une clé i18n dupliquée écrasait un libellé du menu
La section du menu des plugins prenait « Install » pour clé, déjà portée
par l'entrée « 📦 Installation » du menu principal. Dans un littéral de
dict Python la dernière définition gagne, sans erreur ni avertissement :
le menu principal affichait donc « Installer ». La clé de la section est
renommée, la première étant en place depuis longtemps.

Vérifié : le menu principal retrouve « 📦 Installation », et un balayage
des clés ne laisse que trois doublons, tous à valeurs identiques donc
sans effet.

--- EN ---

The plugin menu's section used « Install » as its key, already held by
the main menu's « 📦 Installation » entry. In a Python dict literal the
last definition wins, with no error and no warning: the main menu
therefore showed « Installer ». The section's key is renamed, the first
one having been there far longer.

Checked: the main menu gets « 📦 Installation » back, and a sweep of the
keys leaves only three duplicates, all with identical values and so
without effect.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
3bd9f1edad [FIX] qemu menu : nommer l'URI libvirt, sinon la liste des VM est vide
Sans « --connect », un virsh non root vise qemu:///session : un
hyperviseur SÉPARÉ, où aucune VM du système n'existe. « list --all » y
rend une liste vide, sans erreur ni avertissement. L'URI par défaut de
root masquait l'omission tant que les commandes passaient par sudo ;
appartenir au groupe libvirt donne le droit d'atteindre qemu:///system
mais ne change pas l'URI. Les 40 appels locaux passent donc par un
constructeur unique — dont 19 en liste d'arguments, qui gardaient encore
sudo en dur.

Vérifié : une garde balaie les deux fichiers et échoue si un virsh est
écrit sans URI ; la réintroduire fait rougir.

--- EN ---

Without « --connect », a non-root virsh targets qemu:///session: a
SEPARATE hypervisor, where none of the system's VMs exist. « list --all »
returns an empty list there, with no error and no warning. Root's default
URI masked the omission as long as commands went through sudo; libvirt
group membership grants the right to reach qemu:///system but does not
change the URI. All 40 local calls therefore go through one builder —
19 of them argument lists that still hardcoded sudo.

Checked: a guard sweeps both files and fails if a virsh is written
without the URI; putting one back turns it red.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
f417a9ea86 [ADD] qemu deploy : case 3D à la création, même sans écran virtuel
Une VM sans console peut vouloir un virtio-gpu accéléré — rendu hors
écran, ou émulateur qui tourne dedans — et « auto » ne l'accorde jamais :
il s'abstient sans écran, pour ne pas poser un périphérique vidéo que
personne n'a demandé. La case envoie donc « --gpu on », qui l'accorde
désormais. « --graphics none » est alors écarté : il dit « aucun
affichage », et egl-headless EST un affichage. Le repli le rend quand la
3D tombe, sinon la VM repartirait sur le défaut de virt-install.

Vérifié : 8 tests neufs et 2 sur le repli, rougis par trois mutations.
Le rendu de la case dans le terminal plein écran n'est pas testé.

--- EN ---

A VM without a console may want an accelerated virtio-gpu — offscreen
rendering, or an emulator running inside — and « auto » never grants it:
it abstains without a screen, so as not to add a video device nobody
asked for. The box therefore sends « --gpu on », which now grants it.
« --graphics none » is then dropped: it means « no display », and
egl-headless IS a display. The fallback gives it back when 3D fails,
otherwise the VM would restart on virt-install's default.

Checked: 8 new tests and 2 on the fallback, turned red by three
mutations. The box's rendering in the full-screen terminal is not tested.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
c8d76f1c33 [ADD] qemu deploy : proposer d'effacer un disque orphelin qui bloque
Une création interrompue laisse son qcow2 sans VM définie, et deploy_qemu
refuse ensuite d'écraser : la création échoue APRÈS avoir fait attendre.
Le disque est donc proposé à l'effacement, taille et chemin affichés.
Proposé et non effacé d'office : le même nom peut désigner le disque
d'une VM retirée à la main, dont on voulait garder les données. Un refus
ne laisse pas filer vers l'échec, il redemande. La proposition vient
après la fermeture du formulaire plein écran, parce qu'effacer là demande
root et qu'une invite de mot de passe n'y a nulle part où s'afficher.

Vérifié : 7 tests, rougis par deux mutations — ne pas redemander après un
refus, et sauter la proposition sur le chemin plein écran.

--- EN ---

An interrupted creation leaves its qcow2 with no defined VM, and
deploy_qemu then refuses to overwrite: creation fails AFTER the wait. The
disk is therefore offered for deletion, size and path shown. Offered, not
deleted outright: the same name may designate the disk of a VM removed by
hand, whose data was meant to be kept. A refusal does not drift into
failure, it asks again. The offer comes after the full-screen form
closes, because deleting there needs root and a password prompt has
nowhere to appear inside it.

Checked: 7 tests, turned red by two mutations — not asking again after a
refusal, and skipping the offer on the full-screen path.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
9f94316ab0 [FIX] qemu deploy : recréer la VM sans 3D quand EGL ne démarre pas
Le nœud de rendu existe mais EGL ne s'y initialise pas : QEMU s'arrête
sur « eglInitialize failed » pendant la connexion au moniteur. La
détection ne voit qu'un fichier dans /dev/dri, et rien ne distingue un
GPU utilisable d'un nœud sans pile EGL avant que QEMU n'essaie. La
création réessaie donc sans la 3D, après avoir retiré le domaine de
l'essai raté — sans quoi le nom reste pris. « --gpu on » n'est pas
rétrogradé en silence, et un échec qui n'est pas celui d'EGL n'est pas
rattrapé.

Vérifié : 8 tests et trois mutations. Le chemin réel n'a pas été exécuté,
faute de /dev/dri et de virt-install sur la machine de développement.

--- EN ---

The render node exists but EGL will not initialise on it: QEMU stops on
« eglInitialize failed » while connecting to the monitor. Detection only
sees a file under /dev/dri, and nothing separates a usable GPU from a
node without an EGL stack until QEMU tries. Creation therefore retries
without 3D, after undefining the domain of the failed attempt — the name
would otherwise stay taken. « --gpu on » is not silently downgraded, and
a failure that is not EGL's is not caught.

Checked: 8 tests and three mutations. The real path was not exercised,
for lack of /dev/dri and virt-install on the development machine.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
feb6cd7b12 [FIX] qemu menu : passer par le groupe libvirt plutôt que par sudo
Appartenir au groupe libvirt suffit à joindre qemu:///system : le sudo
écrit en dur n'y ajoutait aucun droit et réclamait un mot de passe à
chaque entrée de menu. La question se tranche en ESSAYANT, jamais en
lisant /etc/group : les groupes d'un processus sont figés à l'ouverture
de session, donc la table dit le déclaré, l'essai le faisable. C'est la
distinction que porte aussi l'avertissement d'avant-installation. Un
hyperviseur distant garde sudo, ses droits ne se sondant pas d'ici.

Vérifié : 10 tests, rougis par deux mutations — lire /etc/group, et
conclure « pas de sudo » sur un sondage mort.

--- EN ---

Membership of the libvirt group is enough to reach qemu:///system: the
hardcoded sudo added no right there and asked for a password at every
menu entry. The question is settled by TRYING, never by reading
/etc/group: a process's groups are frozen at session start, so the table
states what is declared, the attempt what is doable. The pre-install
warning carries that same distinction. A remote hypervisor keeps sudo,
its rights not being probeable from here.

Checked: 10 tests, turned red by two mutations — reading /etc/group, and
concluding « no sudo » from a dead probe.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
d3e8d50953 [FIX] qemu deploy : montrer le message de l'outil quand une VM échoue
Une VM ratée n'affichait que ses quatre dernières lignes, et l'épilogue
« Échec de la commande » avec sa ligne de commande les occupe entièrement :
le message de l'outil tombait juste au-dessus de la fenêtre. La sortie
étant jetée après la boucle, passé l'écran elle n'existait plus nulle
part. Trente lignes en cas d'échec, quatre en cas de réussite, et la
sortie complète va dans un fichier dont le chemin s'affiche. Quand la
commande portait la 3D, le rapport nomme « --gpu off » : le menu ne
l'expose pas, c'est la seule issue depuis là.

Vérifié : 7 tests, dont un nom de VM hostile qui ne doit pas composer un
chemin hors du répertoire de session.

--- EN ---

A failed VM showed only its last four lines, and the « Échec de la
commande » epilogue with its command line fills them entirely: the tool's
own message fell just above the window. The output being discarded after
the loop, past the screen it existed nowhere at all. Thirty lines on
failure, four on success, and the whole output goes to a file whose path
is printed. When the command carried 3D, the report names « --gpu off »:
the menu does not expose it, and it is the only way out from there.

Checked: 7 tests, among them a hostile VM name that must not compose a
path outside the session directory.

Assisted-by: Claude Opus 5
2026-09-03 05:00:55 -04:00
97ccce1def Merge branch 'develop_claude_skills'
Improve claude skills with TODO
2026-09-03 05:00:30 -04:00
d92797d38a [REF] claude : alléger le contexte, deux règles passent en skills
Environ 1 130 tokens étaient chargés à chaque session pour du contenu
dérivable ou écrit deux fois : les deux tableaux d'index décrivaient des
fichiers déjà chargés en entier, et la ligne de format de commit
contredisait 04-code-conventions.md et le hook qui l'applique. Les règles
du générateur et du déploiement ne servent qu'à une tâche : elles se
chargent désormais à la demande, comme les deux skills déjà en place.
L'interdit du générateur, lui, reste dans CLAUDE.md — une interdiction ne
doit pas dépendre de l'ouverture d'une skill.

Vérifié : aucun renvoi vers les fichiers déplacés, et les quatre skills
déclarent un nom qui correspond à leur répertoire.

--- EN ---

About 1,130 tokens loaded every session for content that is derivable or
written twice: the two index tables described files already loaded in
full, and the commit-format line contradicted 04-code-conventions.md and
the hook enforcing it. The code-generator and deployment rules serve one
task each: they now load on demand, like the two skills already in place.
The generator's prohibition stays in CLAUDE.md — a ban must not depend on
a skill being opened.

Checked: no reference points at the moved files, and all four skills
declare a name matching their directory.

Assisted-by: Claude Opus 5
2026-09-02 08:04:15 -04:00
29b12c8ca1 [ADD] qemu arch : yay et bash-completion sur l'invité, guide au MOTD
Une image cloud Arch est nue : ni bash-completion, ni accès à l'AUR. Les
deux arrivent avec l'amorçage, sur la seule branche pacman. yay-bin
plutôt que yay, dont le paquet source compile Go pour le même outil ; la
construction reste sous l'utilisateur de la VM, makepkg refusant root. Le
« || true » qui ferme le bloc porte : le groupe est le dernier membre de
sa liste « || », donc set -e s'y applique et un sudo en échec emporterait
l'installation entière. Le guide de connexion n'annonce yay que si une
installation a eu lieu.

Vérifié : 10 tests, dont « bash -n » sur la commande distante entière et
la survie du bloc sous set -e avec un PATH vide.

--- EN ---

An Arch cloud image is bare: no bash-completion, no AUR access. Both come
with the bootstrap, on the pacman branch alone. yay-bin rather than yay,
whose source package compiles Go for the same tool; the build stays under
the VM user, makepkg refusing root. The « || true » closing the block
carries weight: the group is the last member of its « || » list, so set -e
applies inside it and one failing sudo would take the whole install down.
The login guide announces yay only when an install ran.

Checked: 10 tests, among them « bash -n » over the whole remote command
and the block surviving set -e with an empty PATH.

Assisted-by: Claude Opus 5
2026-09-02 08:04:05 -04:00
736ab3b676 [FIX] qemu setup-host : demander avant de redémarrer l'hôte
Accepter d'installer les paquets QEMU redémarrait la machine sans autre
question : --assume-yes couvrait le gestionnaire de paquets, et la
commande y ajoutait --reboot-if-needed, qui ne demandait rien. Une seule
constante servait la VM qu'on vient de créer et le poste qui la crée.
--reboot-if-needed PROPOSE désormais, sur /dev/tty pour rester visible
quand la sortie est un tuyau, et vaut non par défaut ; un refus laisse
les paquets posés et dit quoi faire. --assume-yes-reboot est le seul
consentement muet, que seul le profil invité porte.

Vérifié : 7 tests, rougis par deux mutations — assume_yes rouvrant la
porte, le menu hôte reprenant le drapeau.

--- EN ---

Accepting the QEMU package install rebooted the machine with no further
question: --assume-yes covered the package manager, and the command
added --reboot-if-needed, which asked nothing. One constant served both
the VM just created and the workstation creating it. --reboot-if-needed
now OFFERS, on /dev/tty so it stays visible when output is a pipe, and
defaults to no; a refusal leaves the packages in place and says what to
do. --assume-yes-reboot is the only silent consent, carried by the guest
profile alone.

Checked: 7 tests, turned red by two mutations — assume_yes reopening the
door, the host menu taking the flag back.

Assisted-by: Claude Opus 5
2026-09-02 07:38:11 -04:00
2435f0f6d3 [ADD] script todo : /todo_generate_code, effort high et règles du dépôt
Les règles à appliquer avant de coder sont éparpillées entre les configs,
les hooks et les modules maison, et la documentation en contredit
plusieurs : autopep8 est recommandé alors que le script sort en 1, aucun
script oca-* n'est installé, la racine n'a ni .pre-commit-config.yaml ni
.pylintrc, et flake8 comme pylint-odoo ne vivent que dans le venv Odoo,
que rien ne lance. Le gabarit énonce ce que l'outillage impose, à effort
high, l'épinglage ultracode restant celui de l'utilisateur.

Vérifié : 146 règles relevées, 142 confirmées contre leur citation, 4
retirées. Deux gardes lient chaque entrée du menu à un gabarit présent
qui déclare le bon nom.

--- EN ---

The rules to apply before coding are scattered across the configs, the
hooks and the in-house modules, and the documentation contradicts several
of them: autopep8 is recommended although the script exits 1, no oca-*
script is installed, the root carries neither .pre-commit-config.yaml nor
.pylintrc, and flake8 as well as pylint-odoo live only in the Odoo venv,
which nothing invokes. The template states what the tooling enforces, at
high effort, the ultracode pin remaining the user's own.

Checked: 146 rules surveyed, 142 confirmed against their citation, 4
dropped. Two guards tie each menu entry to a template that exists and
declares the right name.

Assisted-by: Claude Opus 5
2026-09-02 07:16:23 -04:00
4f85a4f225 [ADD] script todo : /todo_plan_max, planifier avant d'ajouter une entrée
Ajouter une entrée commence par des décisions qu'aucun gabarit
n'imposait : quel menu parent, motif A ou B, quoi faire en cas d'échec,
ce qui est détruit, ce qui touche à une donnée client. La commande les
demande avant d'écrire, planifie avec superpowers quand le plugin est
là, et pose sa spécification dans tasks/, non versionné. Son frontmatter
fixe l'effort à max, seule valeur de l'énumération ; ultracode est un
épinglage de session que l'utilisateur tape, non un réglage de gabarit.

Vérifié : les deux gabarits déployés dans un HOME jetable, relus « à
jour » par l'écran de contexte.

--- EN ---

Adding an entry starts with decisions no template forced: which parent
menu, pattern A or B, what to do on failure, what gets destroyed, what
touches customer data. The command asks them before writing, plans with
superpowers when the plugin is there, and lays its specification in
tasks/, which is not versioned. Its frontmatter sets effort to max, the
only value in the enumeration; ultracode is a session pin the user
types, not a template setting.

Checked: both templates deployed into a throwaway HOME, read back as up
to date by the context screen.

Assisted-by: Claude Opus 5
2026-09-02 06:35:57 -04:00
6847891c1b [ADD] script todo : gérer les plugins Claude Code et leur liste ERPLibre
Rien ne posait un plugin depuis TODO ; la CLI seule le faisait, hors du
menu. L'installation passe par « -y » : la sortie de TODO est un tuyau,
pas un terminal, et la CLI refuse sans lui toute installation qui
exécute une commande déclarée par un marketplace. La liste préférée
s'affiche donc AVANT la confirmation, seule occasion de la lire ; ses
quatre plugins travaillent sur le poste, sans service tiers ni compte.
La recherche lit les manifestes sur le disque, donc hors ligne.

Vérifié : 8 tests neufs, dont la frontière de mot qui sépare deux noms
dont l'un contient l'autre — une recherche naïve en rate trois.

--- EN ---

Nothing installed a plugin from TODO; the CLI alone did, outside the
menu. Installing goes through « -y »: TODO's output is a pipe, not a
terminal, and without it the CLI refuses any install that runs a
command declared by a marketplace. The preferred list is therefore
shown BEFORE the confirmation, the only chance to read it; its four
plugins run on the workstation, with no third party and no account.
Search reads the manifests from disk, hence offline.

Checked: 8 new tests, among them the word boundary separating two names
where one contains the other — a naive search misses three of them.

Assisted-by: Claude Opus 5
2026-09-02 06:35:05 -04:00
c32e7d87c9 [ADD] script todo : déployer /git_prepare_merge depuis le menu Claude
Une fusion apporte plusieurs commits d'un coup, et rien ne guidait les
deux écrits qu'elle demande : l'entrée de changelog et le message de
merge. La commande déployée impose la source — CHANGELOG.base.md, les
fichiers générés étant perdus au prochain doc_markdown — et le corps
bilingue avec son trailer, que le garde-fou ne verra jamais, commit-msg
ignorant tout message ouvrant sur « Merge ». Elle prépare, elle ne
fusionne pas : le message part dans tasks/, non versionné.

Vérifié : 45 tests du menu, et un déploiement dans un HOME jetable que
l'écran de contexte relit « à jour » face à son gabarit.

--- EN ---

A merge lands several commits at once, and nothing guided the two pieces
of writing it needs: the changelog entry and the merge message. The
deployed command imposes the source — CHANGELOG.base.md, the generated
files being lost at the next doc_markdown — and the bilingual body with
its trailer, which the guard rail never sees, commit-msg skipping any
message opening on « Merge ». It prepares, it does not merge: the
message goes to tasks/, which is not versioned.

Checked: 45 menu tests, and a deployment into a throwaway HOME that the
context screen reads back as up to date against its template.

Assisted-by: Claude Opus 5
2026-09-02 06:15:43 -04:00
8bdbf42a31 [ADD] script todo : installer Claude Code et opencode, PATH garanti
Ces installateurs posent leur binaire dans un répertoire du HOME que le PATH
d'un shell ne porte pas toujours : sans la ligne d'export, le binaire est là
et la commande reste introuvable. Le répertoire diffère d'un outil à l'autre,
et l'un des deux écrit déjà sa propre ligne — la présence se teste donc sur
le répertoire, pas sur la graphie, et rien n'est ajouté deux fois.

Le PATH d'un processus est figé depuis son démarrage : un nouveau shell est
nécessaire, ce que la sortie dit. Troisième écrivain dans le fichier de
shell, starship compris, d'où l'écriture mise en commun. Vérifié : 31 tests.

--- EN ---

These installers put their binary in a HOME directory that a shell's PATH
does not always carry: without the export line, the binary is there and the
command stays not found. The directory differs from one tool to the other,
and one of the two already writes its own line — presence is therefore tested
on the directory, not on the spelling, and nothing is added twice.

A process PATH is frozen since its start: a new shell is needed, which the
output says. Third writer into the shell file, starship included, hence the
shared write. Checked: 31 tests.

Assisted-by: Claude Opus 5
2026-09-02 04:51:03 -04:00
371605b90a [IMP] script todo : une icône par entrée du menu Git et Shell
Sept entrées sans repère visuel se lisent une par une. L'icône entre dans la
traduction, qui porte déjà le libellé affiché.

Un glyphe à présentation texte occupe une colonne quand les autres en
occupent deux, et décale la colonne des libellés : il prend deux espaces,
comme 🖥 et ⚙ ailleurs dans le fichier. Rendu vérifié dans les deux langues.

--- EN ---

Seven entries with no visual marker are read one by one. The icon goes into
the translation, which already carries the displayed label.

A text-presentation glyph takes one column where the others take two, and
shifts the label column: it gets two spaces, like 🖥 and ⚙ elsewhere in the
file. Rendering checked in both languages.

Assisted-by: Claude Opus 5
2026-09-02 04:43:43 -04:00
b321052888 [ADD] script todo : Starship depuis le menu Git, renommé Git et Shell
Poser le binaire ne change pas le prompt : c'est la ligne d'initialisation
dans le fichier du shell qui le fait, et les deux étapes échouent séparément.
Le paquet vient de la distribution quand elle le connaît, de l'installateur
amont sinon — starship n'est pas empaqueté partout. Le fichier du shell n'est
demandé que devant plusieurs candidats, et la ligne ne s'écrit qu'une fois.

L'entrée porte sa destination dans « method » : son rang suit le nombre
d'entrées de todo.json, qu'un numéro codé en dur ignorerait. Vérifié : 18
tests.

--- EN ---

Laying down the binary does not change the prompt: the init line in the shell
file does, and the two steps fail separately. The package comes from the
distribution when it knows it, from the upstream installer otherwise —
starship is not packaged everywhere. The shell file is only asked for when
several candidates exist, and the line is written only once.

The entry carries its destination in « method »: its rank follows the number
of todo.json entries, which a hard-coded number would ignore. Checked: 18
tests.

Assisted-by: Claude Opus 5
2026-09-02 04:43:25 -04:00
d31ca9eab9 [UPD] qemu manage : nom de VM sans la version d'une publication continue
Une distribution en publication continue n'a qu'une version, latest : le
segment ne distingue aucune VM d'une autre et sort du nom. Une version
nommée qui coexiste avec d'autres au catalogue y reste, tumbleweed comme
les numérotées.

Le nom se relit dans l'autre sens pour retrouver (distro, version) et
filtrer les outils par distribution : une VM déjà déployée sous l'ancien
nom n'y est plus résolue, la renommer suffit. Vérifié : catalogue rejoué
sans collision, aller-retour du nom, 6 tests.

--- EN ---

A rolling-release distribution has a single version, latest: the segment
tells no VM apart from another and leaves the name. A named version that
coexists with others in the catalogue stays, tumbleweed as much as the
numbered ones.

The name is read back the other way to recover (distro, version) and filter
tools by distribution: a VM already deployed under the old name no longer
resolves there, renaming it is enough. Checked: catalogue replayed without
collision, name round trip, 6 tests.

Assisted-by: Claude Opus 5
2026-09-02 04:13:48 -04:00
93ffb3b7e9 [ADD] script todo : poser merge.conflictStyle=zdiff3 depuis le menu Git
zdiff3 fait figurer la base commune dans les marqueurs de conflit et sort
de la zone contestée les lignes que les deux côtés ont en commun : il reste
moins à arbitrer à la main. Le style demande git 2.35, que toutes les
plateformes supportées dépassent.

La valeur est relue après écriture, « git config » ne rendant rien à
l'écriture. L'entrée est déclarée dans TestGitMenuNumbering : le menu Git
mêle entrées codées en dur et entrées de todo.json, qu'un rang de plus
décale. Vérifié : 117 tests au vert.

--- EN ---

zdiff3 puts the merge base into the conflict markers and lifts out of the
contested area the lines both sides share: less is left to arbitrate by
hand. The style needs git 2.35, which every supported platform exceeds.

The value is read back after writing, as « git config » returns nothing on
write. The entry is declared in TestGitMenuNumbering: the Git menu mixes
hard-coded entries with todo.json ones, which one more rank shifts.
Checked: 117 tests green.

Assisted-by: Claude Opus 5
2026-09-02 04:01:10 -04:00
3dcccf40d9 [FIX] script todo : rtk hors du PATH, résultat d'installation annoncé
Un processus garde le PATH qu'il avait au démarrage : rtk installé dans
~/.local/bin pendant que TODO tourne échappe à shutil.which, et « rtk » nu
sort en 127. Le menu le cherche donc aussi à l'emplacement de
l'installateur et l'appelle par son chemin absolu, sans confondre un
binaire hors PATH avec une absence.

L'installation annonce son résultat : version et chemin, ou échec.
Vérifié : 9 tests neufs, 117 au total.

--- EN ---

A process keeps the PATH it had at startup: rtk installed into
~/.local/bin while TODO runs escapes shutil.which, and a bare « rtk »
exits 127. The menu therefore also looks at the installer's location and
calls the binary by its absolute path, without mistaking a binary outside
the PATH for a missing one.

Installation now reports its outcome: version and path, or failure.
Checked: 9 new tests, 117 in total.

Assisted-by: Claude Opus 5
2026-09-02 03:53:40 -04:00
1cc74c83b4 [FIX] qemu shrink : place mesurée avant sauvegarde, étape annoncée
La sauvegarde double la place occupée et le défaut était OUI : sur un
disque presque plein, une entrée vide lançait une copie qui s'arrête à
mi-course et laisse un .bak tronqué. Les deux tailles passent donc avant
la question, et le défaut bascule à NON quand la place manque.

Le besoin annoncé est la taille ALLOUÉE : « cp --sparse=always » ne
recopie pas les trous d'un qcow2. La sortie du gestionnaire de paquets
enchaînait par ailleurs sur une question portant sur autre chose ;
l'étape se referme d'une ligne.

Vérifié : le défaut remis à OUI sans place, comme la taille apparente au
lieu de l'allouée, font tomber les tests. 4144 verts.

--- EN ---

A backup doubles the space used and the default was YES: on a nearly
full disk, an empty answer started a copy that stops midway and leaves a
truncated .bak. Both sizes now come before the question, and the default
flips to NO when the room is short.

The need shown is the ALLOCATED size: "cp --sparse=always" does not copy
the holes of a qcow2. The package manager output also ran straight into a
question about something else; the step now closes with a line of its
own.

Checked: putting the default back to YES without room, like the apparent
size instead of the allocated one, makes the tests fail. 4144 green.

Assisted-by: Claude Opus 5
2026-08-31 07:51:19 -04:00