Actions composites des lanes agentiques maison (code, fix, review, triage) — ADR-0020 d'infrastructure
  • Python 72.7%
  • Shell 27.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-14 04:27:23 +02:00
exemples fix(securite): sortie de node gardée hors du journal puis préfixée, plus de stop-commands 2026-10-14 04:18:16 +02:00
installer feat: actions persona, installer et lancer pour des lanes agentiques en CI 2026-10-12 17:33:48 +02:00
lancer fix(securite): sortie de node gardée hors du journal puis préfixée, plus de stop-commands 2026-10-14 04:18:16 +02:00
outils fix(securite): fichiers de commande du runner refermés pour verifier, journal suspendu, node tué avant GITHUB_OUTPUT 2026-10-14 04:03:09 +02:00
persona feat: actions persona, installer et lancer pour des lanes agentiques en CI 2026-10-12 17:33:48 +02:00
personas feat(review): la revue voit l'état de la CI de la tête (#12) 2026-10-14 00:42:45 +02:00
reglages fix(securite): contrôle des chemins interdits contournable par un nom non ASCII ou un renommage 2026-10-13 22:53:54 +02:00
tests fix(securite): sortie de node gardée hors du journal puis préfixée, plus de stop-commands 2026-10-14 04:18:16 +02:00
CONTRAT.md fix(securite): sortie de node gardée hors du journal puis préfixée, plus de stop-commands 2026-10-14 04:18:16 +02:00
LICENSE feat: actions persona, installer et lancer pour des lanes agentiques en CI 2026-10-12 17:33:48 +02:00
README.md Merge branch 'ticket-13' into integration-12-13-16-17 2026-10-14 00:43:28 +02:00

lanes

Des agents de code en CI, sur Forgejo Actions (ou tout runner compatible avec les actions GitHub), sans leur confier le jeton du dépôt. Une « lane » est un workflow déclenché par une étiquette :

Lane Étiquette posée sur L'agent… Le workflow…
triage un ticket vérifie le ticket dans le code, le classe, propose des étiquettes pose les étiquettes autorisées, commente
code un ticket implémente, committe vérifie, pousse la branche, ouvre la PR
review une PR relit, rend un verdict publie la revue
fix une PR corrige la CI rouge ou les constats de revue vérifie, pousse en avance rapide, commente

L'agent travaille ; un job suivant, sans agent, contrôle ce qu'il a livré et publie. La fusion reste humaine.

Contenu

Chemin Rôle
persona/, installer/, lancer/ Les trois actions composites, décrites plus bas
personas/ Les quatre personas (sous-agents au format Claude Code)
reglages/ Leurs permissions : ecriture.json (code, fix), lecture.json (review, triage)
CONTRAT.md Ce que chaque persona reçoit et livre, ce que le workflow doit contrôler, ce qui a été mesuré. Fait foi
exemples/ Les quatre workflows complets, prêts à copier
outils/installer.py Installe ou réépingle les quatre workflows dans un dépôt, et ses étiquettes
tests/ test_lanes.py (sans modèle), essai-local.sh (essai réel sur un dépôt jetable), variance.yml (chaque cas cinq fois, en CI)

Le modèle de sécurité

Le jeton automatique d'un job est dans l'environnement de chaque étape, et un agent qui a un shell peut écrire tout ce que son compte peut écrire. D'où :

  1. L'agent tourne sous node, avec env -i : il ne voit que sa clé d'API, jamais le jeton du dépôt.
  2. Avant de le lancer, lancer cherche tout ce que node peut écrire et échoue si l'agent pourrait modifier ce que root exécutera ou lira ensuite : les fichiers de commande du runner (GITHUB_ENV…), les actions, /usr, ses propres scripts.
  3. L'agent ne publie rien. Il livre un fichier (rapport, verdict, corps de PR) et, en mode écriture, un bundle git de ses commits. Les tests du dépôt tournent dans un job sans aucun secret ; le job qui publie refuse toute livraison qui contient un secret, touche la CI ou réécrit l'historique.
  4. Les permissions sont fermées par défaut : en lecture, pas de shell ; en écriture, git local seulement, sans push. Un texte de ticket ou de PR est une donnée, jamais une instruction, et les personas sont écrites pour le traiter ainsi.

CONTRAT.md détaille chaque point et ce qu'il ne couvre pas.

Démarrer

  1. Extraire ce dépôt à l'empreinte de commit choisie, puis, depuis lui :

    python3 outils/installer.py --forge https://votre.forge/proprietaire \
        --empreinte <empreinte> --cible ../votre-depot \
        --verification 'npm test' --courriel bot@votre.forge
    

    Il écrit les quatre workflows dans .forgejo/workflows/ du dépôt cible, tous les marqueurs remplacés, et échoue s'il en reste un. Toujours une empreinte, jamais une branche ni une étiquette : c'est elle qui fixe le code des actions et le texte des personas. Rejoué avec une autre empreinte, il réépingle et garde la vérification et le courriel en place. Avec --etiquettes proprietaire/depot et un jeton dans FORGEJO_TOKEN, il liste les étiquettes de l'étape 4 qui manquent ; --appliquer les crée.

    À la main : copier un workflow de exemples/ dans .forgejo/workflows/ et y remplacer les trois marqueurs : forge.example/proprietaire par l'adresse de ce dépôt-ci sur votre forge (ou d'une copie), sans le nom du dépôt ; proprietaire/lanes (entrée depot de l'action persona) par son chemin propriétaire/dépôt ; EMPREINTE_LANES par l'empreinte.

  2. Adapter VERIFICATION (les tests du dépôt) dans lane-code.yml et lane-fix.yml si --verification ne l'a pas fait, et le courriel des commits du bot (auteur-courriel).

  3. Poser les secrets : ANTHROPIC_API_KEY ; pour code, LANE_BOT_TOKEN, jeton d'un compte de bot qui écrit sur le dépôt (sur Forgejo, le jeton automatique ne peut pas ouvrir de PR).

  4. Créer les étiquettes de déclenchement (triage, code, review, fix), à la main ou par outils/installer.py --etiquettes.

  5. Pour triage, créer aussi les étiquettes de statut ready-for-agent, ready-for-human et needs-info : la lane ne pose que des étiquettes qui existent, et sans elles le statut ne se lit que dans son commentaire. Elles ne déclenchent rien ; seule code lance une implémentation, et c'est un geste délibéré. --etiquettes crée les deux premières ; needs-info reste à créer si le dépôt n'a pas d'équivalent. Un dépôt qui documente sa table d'étiquettes dans docs/agents/triage-labels.md (convention des skills d'ingénierie) la voit suivie par la lane, et elle borne ce que la lane peut poser ; sans table, seuls Kind/*, Status/*, Reviewed/Confirmed, ready-for-* et needs-info le sont (liste blanche, CONTRAT.md). Retirer de DECLENCHEURS, dans lane-triage.yml, les lanes non installées n'est pas nécessaire : ces noms ne sont jamais proposés.

  6. CI du dépôt : la PR de code déclenche la CI du dépôt, qui exécute le code de l'agent avec le jeton automatique du job, en écriture. Protéger la branche par défaut (push et fusion sur liste blanche) et faire tourner le code d'une PR sous node, env -i, comme le job verifier des exemples : CONTRAT.md, « CI aval ». installer.py signale une CI qui ne le fait pas et, avec --etiquettes, une branche par défaut mal protégée.

Prérequis du runner : des jobs en conteneur sous root, avec un utilisateur node, python3, git et runuser (l'image node:22-bookworm, épinglée par empreinte dans les exemples).

Les actions

Action Rôle
persona Copie une persona et ses réglages depuis un dépôt de personas (ce dépôt-ci, ou le vôtre), à une empreinte de commit fixée
installer Installe Claude Code à une version épinglée, rendu à root
lancer Vérifie ce que l'agent pourra écrire, puis lance la persona sous node, environnement vidé ; livre resultat.json, son fichier et, en écriture, le bundle

lancer attend du workflow, avant lui : /tmp/lane/persona.md, /tmp/lane/reglages.json (action persona), /tmp/lane/message.txt (la demande), /tmp/lane/consignes.md (les consignes du dépôt, lues sur la branche cible), le dépôt extrait et le dossier de sortie donnés à node. Les entrées de chaque action sont décrites dans son action.yml.

Modèles et points d'accès

Le moteur est Claude Code ; le modèle et le point d'accès se choisissent par les entrées de lancer :

Entrée Effet
modele Modèle de la persona (claude-sonnet-5-5 par défaut). Prime sur le model d'une persona
url-api Point d'accès compatible avec l'API Messages d'Anthropic : passerelle LiteLLM (vers Bedrock, Vertex ou d'autres familles de modèles), OpenRouter…
cle-api / jeton-api Clé (ANTHROPIC_API_KEY) ou jeton porteur (ANTHROPIC_AUTH_TOKEN), selon le point d'accès
modele-leger Modèle des tâches annexes du moteur

Les garde-fous ne dépendent pas du modèle, mais la qualité du travail et le respect du format de sortie, que le job de publication contrôle, en dépendent : rejouer tests/essai-local.sh avant de changer de modèle.

D'autres moteurs pourront s'ajouter (entrée moteur, script lancer/moteurs/<nom>.sh) à condition d'offrir l'équivalent de chaque garde-fou listé en tête de moteurs/claude-code.sh.

Licence

MIT, voir LICENSE.