Créer une VM de tête pour héberger un hyperviseur qu'on possède déjà coûte cinq minutes ET un étage d'imbrication — donc de la lenteur, puisque c'est elle qu'on mesure. « --hote » part d'un hôte existant ; le menu le propose sans le rechercher, l'hôte Proxmox déjà retenu étant lu par _pve_host(ask=False). Trois conséquences que le code ne tirait pas : - le plan se dimensionne sur la RACINE, lue par ssh. Le dimensionner sur la machine locale quand les étages vivent ailleurs annoncerait des étages qui ne tiennent pas ; - les délais comptent la profondeur ABSOLUE. Un enfant de niveau 1 posé dans une racine déjà au troisième étage est en réalité au quatrième, et héritait de délais quatre fois trop courts — le défaut même que « delai » raconte avoir corrigé ; - la racine n'est pas un étage atteint. L'y compter décalait de un le total et le code de sortie ; elle va dans une clé à part, et jamais « cree ». « sudo » est DÉDUIT de « id -u » et non supposé, et une racine illisible fait renoncer au lieu d'inventer une capacité. Le menu offre les deux piles et défait chacune séparément — elles partagent le dossier des rapports mais chacune ne connaît que les siens. Un test vérifie que toute entrée affichée a son branchement : ils sont couplés par position, sans garde. 80 tests, quatre garde-fous morts sous mutation. --- EN --- Creating a head VM to host a hypervisor you already own costs five minutes AND one level of nesting — that is, slowness, which is the very thing being measured. "--hote" starts from an existing host; the menu offers it without searching, reading the already-chosen Proxmox host via _pve_host(ask=False). Three consequences the code did not draw: - the plan is sized on the ROOT, read over ssh. Sizing it on the local machine while the levels live elsewhere would announce levels that do not fit; - delays count ABSOLUTE depth. A level-1 child placed in a root already at the third level is really at the fourth, and inherited delays four times too short — the very defect "delai" recounts having fixed; - the root is not a level reached. Counting it shifted the total and the exit code by one; it goes in its own key, and never as "cree". "sudo" is DEDUCED from "id -u" rather than assumed, and an unreadable root makes us give up instead of inventing a capacity. The menu offers both stacks and undoes each separately — they share the report directory but each knows only its own. A test checks that every displayed entry has its branch: they are coupled by position, with no guard. 80 tests, four guards die under mutation. Assisted-by: claude-opus-5 (cherry picked from commit c2ab1a968346458925f55fc95619eb4ebd9d3efa) |
||
|---|---|---|
| .. | ||
| auto_ask.py | ||
| database_manager.py | ||
| deploy_form_extras.py | ||
| deploy_form_lib.py | ||
| deploy_form_plan.py | ||
| kdbx_manager.py | ||
| logo_ascii.txt | ||
| longtest_menu.py | ||
| migration_form.py | ||
| migration_stats.py | ||
| migration_status.py | ||
| migration_status_tui.py | ||
| proxmox_deploy_form.py | ||
| proxmox_menu.py | ||
| qemu_access.py | ||
| qemu_deploy.py | ||
| qemu_deploy_form.py | ||
| qemu_hardware.py | ||
| qemu_install.py | ||
| qemu_install_monitor.py | ||
| qemu_manage.py | ||
| qemu_menu.py | ||
| README.base.md | ||
| README.fr.md | ||
| README.md | ||
| source_todo.sh | ||
| textual_setup.py | ||
| todo.json | ||
| todo.py | ||
| todo_example.json | ||
| todo_file_browser.py | ||
| todo_i18n.py | ||
| todo_prefs.py | ||
| todo_telemetry.py | ||
| todo_upgrade.py | ||
| version_manager.py | ||
TODO is an assistant robot to use ERPLibre
Execute it with ./script/todo/todo.py or make todo.
For a new project, copy todo_example.json to private/todo/todo_override.json | private/todo/todo_override_private.json and edit it.
The mail/ package is the mail client reachable from Assistant > Mail:
several IMAP/SMTP accounts, a local cache, and a Textual TUI. See
../../doc/EMAIL.md.
Where the code lives
todo.py carries the menus and the general helpers. Everything around a
single subject sits in its own file, and the whole thing is assembled by
mixins on the TODO class — one file, one subject, its header states its
boundary.
| File | What it owns |
|---|---|
todo.py |
the menus, the configuration, the general helpers |
qemu_menu.py |
the QEMU/KVM menu, the image catalogue, the statistics |
qemu_deploy.py |
deciding then running a deployment |
qemu_install.py |
the recipes run inside a VM |
qemu_manage.py |
lifecycle, disks, hardware, cleanup, addresses |
qemu_access.py |
SSH, tunnels, consoles, Android emulator |
proxmox_menu.py |
the same, on a REMOTE Proxmox VE host |
The two deployment forms — libvirt here, Proxmox over there — ask the same questions, so they share a foundation rather than each holding a copy:
| File | What it owns |
|---|---|
deploy_form_lib.py |
pure logic (sizes, plan, totals, spec), the shared CSS, the resource-row factory, the progress view |
deploy_form_plan.py |
the plan's gestures: overrides, locks, copies, renaming, free values |
qemu_deploy_form.py |
what QEMU/KVM adds: desktops, tools, branches, install profiles |
proxmox_deploy_form.py |
what Proxmox adds: host, storage, bridge, VMID, address |
A form inherits PlanMixin and provides three hooks: which presets each
resource offers, the name a VM would fall back to, and what a lock freezes.
test_todo_deploy_form_lib.py fails if a form redefines a gesture the
foundation already carries — that is what keeps the architecture from drifting
back into two copies.