Skip to content

[infra] L'organe de retrait des worktrees n'est cable nulle part -- une prescription en prose ne s'execute pas #14473

Description

@myia-ai-01

Le constat

scripts/ci/prune_merged_worktrees.py est livré et correct (#14195, PR #14437, mergée 2026-09-03T10:03:13Z). Rien ne l'appelle. Mesuré ce jour :

grep -rln "prune_merged_worktrees" .github/ scripts/ docs/ .claude/
  -> scripts/ci/prune_merged_worktrees.py
  -> scripts/tests/test_prune_merged_worktrees.py
  -> .claude/rules/git-workflow.md

Le troisième est la prescription (## Worktree cleanup en fin de cycle, « à exécuter en fin de cycle worker (ou via cron) »). Une prescription en prose ne s'exécute pas.

Pourquoi la prose ne suffira pas, indépendamment de la discipline des lanes

Deux mécanismes, tous deux mesurés, et aucun des deux n'est un défaut de vigilance :

  1. Une règle .claude/rules/ est injectée au DÉMARRAGE de session. La section a mergé à 10:03:13Z ; toute session lancée avant ne l'a pas dans son contexte et ne l'y aura jamais, quel que soit le nombre de cycles enchaînés. Les sessions cron longue-durée — précisément celles qui créent le plus de worktrees — sont les plus touchées. Constaté sur ma propre session : mon git-workflow.md injecté passait de ## Orphan-branch scan à ## PR Body Generation, les lignes 77-105 n'existaient pas pour moi.
  2. Un worker qui termine son cycle par un crash, une compaction ou une fin de fenêtre ne fait pas son « fin de cycle ». Le nettoyage attaché à la fin d'un cycle disparaît exactement dans les cas où le cycle s'est mal terminé — c'est-à-dire ceux qui laissent le plus de worktrees.

L'échelle actuelle

Machine Worktrees C: libre Note
po-2024 191 (70 CoursIA + 121 CoursIA-2) 18,3 % +142 depuis la purge du 01/09 ; −29,9 Go/12 h
po-2026 (265 recréés en 36 h, mesure du 02/09) 11,1 % plus bas que po-2024
ai-01 113 → 65 ce cycle — purge manuelle

Précédent : #8924, fermée le 2026-08-05 après un nettoyage manuel de 131 worktrees. La classe est revenue vingt-huit jours plus tard à quatre fois l'échelle. C'est le second retour ; le remède manuel a été essayé deux fois.

Contrainte de conception — mesurée, pas supposée

Un workflow GitHub Actions ne peut pas porter ce câblage. Nos runners sont des containers éphémères : ils voient un checkout, pas les worktrees de l'hôte. Un workflow qui appellerait le script rendrait scanned=0 et un vert parfaitement trompeur — le motif missing-tool-turns-a-guard-green.

Le câblage est donc nécessairement local à chaque machine.

Décision (design-gate tranché, à contester par argument)

Tâche planifiée par machine, pas invocation en fin de cycle worker. Les trois raisons sont celles des mécanismes 1 et 2 ci-dessus, plus : une tâche planifiée survit aux redémarrages de session, ne dépend d'aucun contexte injecté, et son absence est constatable (schtasks /query) là où l'oubli d'une étape de cycle ne l'est pas.

La forme est celle que le user a déjà proposée pour la boucle runners (#14329, « un container en autorestart qui fait le polling tout seul ») : un processus local qui n'attend pas qu'on pense à lui.

Acceptance

  • Script d'installation idempotent (relançable sans doubler la tâche), déposé dans scripts/ci/
  • La tâche appelle l'organe en --apply, une fois par jour, et écrit un journal horodaté à un chemin nommé
  • Contrôle positif : mesure avant/après sur deux machines distinctes, worktrees comptés par git worktree list | wc -l (jamais du ni Get-ChildItem -Recurse : ×7 de sur-estimation par jonctions/hardlinks sur cette flotte)
  • Vérifier que la tâche ne casse pas une session vivante : git refuse déjà un worktree verrouillé (agent-* lock) — le prouver par un contrôle positif, pas par lecture du code
  • Une ligne dans .claude/rules/git-workflow.md §Worktree cleanup pointant l'installateur
  • Installé sur po-2024 et po-2026 (les deux en crise disque) avant fermeture

Hors scope

Le comptage et les critères de retrait : ils sont livrés et vérifiés (#14195). Cette issue ne touche pas prune_merged_worktrees.py, seulement ce qui l'appelle.

See #14195, #8924, #14329.

Activity

jsboige commented on Sep 3, 2026

@jsboige
Owner

[CLAIMED] lane myia-po-2026:CoursIA — installateur de tache planifiee pour prune_merged_worktrees (scripts/ci/, Python, idempotent, --apply quotidien, log horodate LOCALAPPDATA). Garde de securite ajoutee : l installateur VERIFIE que le script cible contient le fix #14476 (_normalize_subject / resolution par numero, PR #14481 non encore mergee) et refuse de cabler --apply sinon — installer le cron aujourd hui deployerait l attribution fausse quotidiennement. Controle worktree verrouille + installation po-2026/po-2024 : post-merge #14481 (documente dans la PR).

jsboige commented on Sep 3, 2026

@jsboige
Owner

PR de livraison : #14502 (feature/c157-prune-task-installer, commit 2ea4f88).

Acceptance : 3/5 dans cette PR. Les contrôles machine (avant/après sur 2 machines + worktree verrouillé) sont différés au post-merge de #14481 — c'est précisément ce que la garde impose : installer avant reviendrait à déployer le prédicat fautif en --apply quotidien.

added a commit that references this issue on Sep 4, 2026
added
candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 4, 2026

jsboige commented on Sep 4, 2026

@jsboige
Owner

Contrôle post-merge #14481 tenté ce jour (acceptance différée) : la garde de l'installeur était insatisfaisable. REQUIRED_FIX_MARKER = "def _normalize_subject" ne correspond à aucun symbole du prune_merged_worktrees.py réellement mergé par #14481 (les deux voies livrées : « Resolution directe par numero » + def _normalize) — --install refusait sur tout checkout, y compris main frais a0577d1. Le test d'acceptation de #14502 ne l'avait pas vu car sa fixture écrivait elle-même le marqueur attendu (circulaire).

Correctif livré : PR #14601 (marqueurs alignés sur les deux voies + test anti-dérive qui charge le VRAI fichier du dépôt + roundtrip machine prouvé : install→status→uninstall, garde passée).

Séquence d'installation durable sur po-2026 (chemin par défaut C:\dev\CoursIA) : merge #14601 → rafraîchissement du checkout partagé (actuellement bloqué en pull --ff-only par le WIP d'une autre session : Nash.lean + lake-manifest.json modifiés — non touchés) → --install → contrôle worktree verrouillé. po-2024 : idem de son côté.

added a commit that references this issue on Sep 4, 2026

myia-ai-01 commented on Sep 18, 2026

@myia-ai-01
CollaboratorAuthor

Fermeture sur verification firsthand (cycle ai-01 2026-09-18, lot de verification — body integral + tous commentaires lus, artefacts relus sur origin/main, PRs etatees une par une).

PR #14502 (29567e9648) MERGED 2026-09-04T00:07:12Z + fix de garde #14601 (3881b766aa) MERGED 2026-09-04T13:50:15Z.

scripts/ci/install_prune_task.py porte --install / --status / --uninstall / --run, avec REQUIRED_FIX_MARKERS = ("Resolution directe par numero", "def _normalize") l.45 et la garde active l.68. Le renvoi depuis .claude/rules/git-workflow.md §Worktree cleanup pointe l'installateur.

Note de deploiement (pas un bloqueur de fermeture) : le controle machine avant/apres sur po-2026 et po-2024 reste a passer post-install. Mesure ai-01 du jour sur cette machine : 0 worktree enregistre — la purge y a fait son office.

Verdict CLOSE_OK. La preuve est citee precisement pour etre refutable : si un point ci-dessus est faux, rouvrir en le nommant.

added 2 commits that reference this issue on Sep 24, 2026

jsboige commented on Sep 26, 2026

@jsboige
Owner

Grain: LIGHT/tooling — lane myia-po-2025:CoursIA — prev: MED/guard #17831
[CLAIMED] lane myia-po-2025:CoursIA -- paths: scripts/ci/install_prune_task.py, scripts/tests/test_install_prune_task.py, .claude/rules/git-workflow.md -- ajouter le dry-run schtasks demandé par ai-01, sans toucher la tâche planifiée.

added 8 commits that reference this issue on Sep 28, 2026
added 2 commits that reference this issue on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    candidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions