ia_dev/.cursor/agents/README.md

121 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Gitea issues scripts et agents
Dossier dédié au traitement des tickets (issues) Gitea du dépôt **4nk/lecoffre_ng** (https://git.4nkweb.com/4nk/lecoffre_ng/issues). Toute la logique d'appel API et Git est dans les scripts ; les agents orchestrent et appellent /fix ou /evol.
## Agents (.cursor/agents/)
| Agent | Fichier | Rôle |
|-------|---------|------|
| **agent-loop** | `agent-loop.md` | Orchestre la boucle de récupération des mails et le traitement : lance les 2 boucles en arrière-plan (récupération + traitement, pas de timeout) ou exécute x fois (récupération 1 fois puis traitement 1 fois via gitea-issues-process). |
| **gitea-issues-process** | `gitea-issues-process.md` | Traite les issues Gitea et les mails en attente : liste les issues/mails, crée des branches, lance /fix ou /evol, /push-by-script ; workflow mails (fil, réponse réelle, marquage lu). |
Spooler tickets (nouveau) : mails dans **projects/<id>/data/issues/** (filtre par `tickets.authorized_emails` dans conf.json), pas de « non lu », aucun enregistrement supprimé. Format : `gitea-issues/TICKETS_SPOOL_FORMAT.md`. Récupération : `./ia_dev/gitea-issues/tickets-fetch-inbox.sh`. Référence boucle mails (legacy) : `gitea-issues/AGENT_LOOP.md`. Hook Cursor : `sessionStart``.cursor/hooks/remonter-mails.sh` (lit `projects/<id>/data/issues/*.pending`).
## Contexte d'exécution
- **Emplacement** : `gitea-issues/` est dans le sous-module **ia_dev** du dépôt projet. Chemin typique : `<racine_projet>/ia_dev/gitea-issues/`. Fonctionne pour tout projet utilisant ia_dev de la même manière.
- **Projet cible** : le projet est identifié **dynamiquement** par le fichier `../ai_project_id` (à la racine du dépôt projet, parent de `ia_dev`). Son contenu (slug) sert à charger la config dans `ia_dev/projects/<id>/`. Changer de projet = changer le dépôt (ou le contenu de `ai_project_id`) ; aucun chemin à hardcoder.
- **Lancement** : le chat Cursor et les scripts sont lancés depuis **ia_dev** (`<racine_projet>/ia_dev/`), mais les opérations (issues, mails, déploiement) concernent le dépôt **parent** (`../` = racine projet). Invoquer les scripts depuis la racine du dépôt projet : `cd <racine_projet> && ./ia_dev/gitea-issues/<script>.sh`. Depuis le workspace ia_dev, racine projet = `..`.
- **Secrets et logs** : `.secrets` est sous **ia_dev** (`ia_dev/.secrets`, soit `./.secrets` depuis ia_dev), et **ne dépend pas du projet parent**. Les scripts résolvent la racine pour `.secrets` et `logs` via le répertoire contenant `gitea-issues` (ia_dev), afin que la config IMAP/SMTP et les logs soient les mêmes quel que soit le projet ; un même clone ia_dev peut servir plusieurs projets configurés par `../ai_project_id`.
## Prérequis
- **jq** : `apt install jq` ou `brew install jq`
- **Token Gitea** : variable denvironnement `GITEA_TOKEN` ou fichier `.secrets/gitea-issues/token` (contenu = le token, non versionné). Créer le token dans Gitea : Settings → Applications → Generate New Token (scopes `read:issue`, `write:issue` si commentaires).
## Scripts (depuis la racine du dépôt)
| Script | Usage | Description |
|--------|--------|-------------|
| `list-open-issues.sh` | `./gitea-issues/list-open-issues.sh [--lines] [--limit N]` | Liste les issues ouvertes (JSON ou lignes `number\|title\|state`). |
| `get-issue.sh` | `./gitea-issues/get-issue.sh <num> [--summary]` | Détail dune issue (JSON ou résumé texte). |
| `print-issue-prompt.sh` | `./gitea-issues/print-issue-prompt.sh <num>` | Affiche titre + corps pour fournir la consigne à lagent. |
| `create-branch-for-issue.sh` | `./gitea-issues/create-branch-for-issue.sh <num> [base]` | Crée et checkout la branche `issue/<num>` depuis `base` (défaut `test`). |
| `comment-issue.sh` | `./gitea-issues/comment-issue.sh <num> <message>` ou `echo "msg" \| ./gitea-issues/comment-issue.sh <num> -` | Ajoute un commentaire à lissue. |
| `mail-list-unread.sh` | `./gitea-issues/mail-list-unread.sh` | Liste les mails **non lus envoyés à l'alias** (MAIL_FILTER_TO, défaut ai.support.lecoffreio@4nkweb.com) ; lecture seule ; sortie : UID, Message-ID, From, To, Subject, Date, Body. Aucun autre mail n'est listé. |
| `mail-get-thread.sh` | `./gitea-issues/mail-get-thread.sh <uid>` | Récupère **tout le fil** (conversation) du mail donné : tous les messages liés par References/In-Reply-To, tri chronologique (ancien → récent). Même format de sortie que mail-list-unread. À utiliser avant de décider ou répondre sur un mail. |
| `mail-send-reply.sh` | `./gitea-issues/mail-send-reply.sh --to <addr> --subject "..." [--body "..." \| stdin] [--in-reply-to "<msg-id>" [--references "..."]]` | Envoie une réponse par mail via le Bridge (SMTP) ; signature « Support IA du projet Lecoffre.io » / ai.support.lecoffreio@4nkweb.com ajoutée automatiquement. |
| `mail-create-issue-from-email.sh` | `./gitea-issues/mail-create-issue-from-email.sh --uid <uid> [--title "..." ] [--body "..."]` | Crée une issue à partir dun mail (UID), optionnel titre/corps formalisés ; marque le mail lu. |
| `mail-mark-read.sh` | `./gitea-issues/mail-mark-read.sh <uid>` | Marque un mail comme lu. |
| `mail-thread-log.sh` | `./gitea-issues/mail-thread-log.sh get-id \| init \| append-sent \| append-issue \| append-commit ...` | **Log par fil** : un fichier par conversation dans `projects/<id>/logs/gitea-issues/threads/` (échanges reçus/envoyés, tickets, commits). `get-id --uid <uid>` affiche `THREAD_ID=...` ; `init --uid <uid>` crée/met à jour le fichier ; `append-sent/issue/commit` enregistrent une réponse, une issue ou un commit. |
| `mail-to-issue.sh` | `./gitea-issues/mail-to-issue.sh` | **Batch** : crée une issue par mail non lu (titre = sujet, corps = texte + From), marque lus. À éviter si on suit le workflow agent (voir cidessous). |
| `agent-loop.sh` | `./ia_dev/gitea-issues/agent-loop.sh [interval_sec]` | **Boucle de surveillance** : exécute périodiquement `mail-list-unread.sh`, met à jour un fichier témoin (`projects/<id>/logs/gitea-issues/agent-loop.status`) et écrit les mails en attente dans `agent-loop.pending`. Voir `gitea-issues/AGENT_LOOP.md`. |
| `agent-loop-treatment.sh` | `./ia_dev/gitea-issues/agent-loop-treatment.sh` | **Boucle traitement** : vérifie périodiquement `agent-loop.pending` ; si non vide, lance l'agent Cursor (workflow gitea-issues-process) pour traiter les mails. À lancer en arrière-plan (pas de timeout). |
| `agent-loop-retrieval-once.sh` | `./ia_dev/gitea-issues/agent-loop-retrieval-once.sh` | **Récupération une fois** (legacy, basé non lu) : exécute `mail-list-unread.sh` et écrit dans `agent-loop.pending`. Utilisé par l'agent agent-loop pour les cycles « x fois ». |
| `tickets-fetch-inbox.sh` | `./ia_dev/gitea-issues/tickets-fetch-inbox.sh` | **Récupération par expéditeurs autorisés** : filtre `tickets.authorized_emails` (conf.json), pas de marquage lu/non lu. Écrit les nouveaux mails dans `projects/<id>/data/issues/<date>_<from>_<uid>.pending` (JSON). Voir `TICKETS_SPOOL_FORMAT.md`. |
Variables optionnelles : `GITEA_API_URL`, `GITEA_REPO_OWNER`, `GITEA_REPO_NAME`, `GITEA_ISSUES_DIR`.
### Création dissues depuis les mails (IMAP) workflow agent
**Ne pas enchaîner directement** : lagent doit dabord lire les non lus, formaliser lissue ou répondre par mail, et ne créer/traiter quau moment où la demande est prête.
1. **Lire les non lus** : `./gitea-issues/mail-list-unread.sh` (ne marque pas les mails comme lus).
2. **Pour chaque mail** : consulter **tout l'historique du fil** avec `./gitea-issues/mail-get-thread.sh <uid>`, créer/mettre à jour le **log du fil** avec `./gitea-issues/mail-thread-log.sh init --uid <uid>` (sortie `THREAD_ID=...` à conserver), puis décider soit denvoyer une réponse directe (demande dinfos) via `mail-send-reply.sh`, soit de formaliser et créer lissue avec `mail-create-issue-from-email.sh` (optionnel `--title` / `--body` formalisés). Si la demande est une correction/évolution prête : créer lissue, traiter (fix/evol), commenter lissue, répondre au mail via `mail-send-reply.sh` (avec `--in-reply-to` pour le fil). **Le corps de la réponse** doit contenir la **réponse réelle** à la question (ex. si le mail demande « Décrit les rôles », le body = une description des rôles), jamais le sujet du mail ni la question reçue.
3. **Réponses aux mails** : toujours via le Bridge avec `mail-send-reply.sh`. Le `--body` doit être la **réponse réelle** rédigée par l'agent (contenu de la réponse à la demande), pas le sujet du mail, pas la question reçue, pas un message précédent du fil. Chaque envoi est enregistré dans le log du fil avec `mail-thread-log.sh append-sent --thread-id <id> --to <addr> --subject "..." --body "..."` pour tracer l'expéditeur, le titre et le corps de la réponse envoyée.
**Prérequis :**
- Python 3 (stdlib : imaplib, email, smtplib, json, urllib).
- Token Gitea : comme les autres scripts (`GITEA_TOKEN` ou `.secrets/gitea-issues/token`).
- Config IMAP/SMTP : copier `gitea-issues/imap-bridge.env.example` vers `.secrets/gitea-issues/imap-bridge.env`. Pour la boucle agent (optionnel) : `agent-loop.env.example` vers `.secrets/gitea-issues/agent-loop.env` (voir AGENT_LOOP.md). Renseigner `IMAP_USER`, `IMAP_PASSWORD` (et optionnellement `SMTP_*` pour lenvoi ; par défaut SMTP reprend les mêmes host/port Bridge 1025). Optionnel : `MAIL_FILTER_TO=ai.support.lecoffreio@4nkweb.com` (seuls les mails envoyés à cette adresse sont listés).
- Proton Mail Bridge (ou serveur IMAP/SMTP) en cours dexécution.
**Scripts :** `mail-list-unread.sh`, `mail-get-thread.sh`, `mail-thread-log.sh`, `mail-send-reply.sh`, `mail-create-issue-from-email.sh`, `mail-mark-read.sh`. Le script batch `mail-to-issue.sh` reste disponible mais ne doit pas être utilisé dans le cadre du workflow agent (liste → lecture du fil → log du fil → décision → création/ réponse). Le script **`agent-loop.sh`** permet de lancer une boucle de surveillance des mails avec fichier témoin ; voir `gitea-issues/AGENT_LOOP.md`.
## API Wiki (tests préalables)
Script de test de lAPI Wiki Gitea pour le même dépôt (prérequis à une éventuelle migration de `docs/` vers le wiki) :
| Script | Usage | Description |
|--------|--------|-------------|
| `wiki-api-test.sh` | `./gitea-issues/wiki-api-test.sh [--create]` | Teste GET list pages, GET page Home ; avec `--create` : POST une page test puis DELETE. |
**Prérequis :** même token que les issues (`GITEA_TOKEN` ou `.secrets/gitea-issues/token`). Pour lécriture (création / suppression de pages), le token doit avoir les droits décriture sur le dépôt.
**Endpoints utilisés (référence Gitea API 1.25) :**
- `GET /repos/{owner}/{repo}/wiki/pages` — liste des pages
- `GET /repos/{owner}/{repo}/wiki/page/{pageName}` — contenu dune page (ex. `Home`)
- `POST /repos/{owner}/{repo}/wiki/new` — créer une page (body : `title`, `content_base64`, `message`)
- `PATCH /repos/{owner}/{repo}/wiki/page/{pageName}` — modifier une page
- `DELETE /repos/{owner}/{repo}/wiki/page/{pageName}` — supprimer une page
Si le wiki na jamais été initialisé (aucune page créée via linterface), les GET peuvent renvoyer 404 ou une liste vide. **Initialiser le wiki** : aller sur https://git.4nkweb.com/4nk/lecoffre_ng/wiki et créer au moins une page (ex. « Home ») via linterface, puis relancer le script avec un token valide.
**Branche par défaut du wiki :** si lAPI renvoie `object does not exist [id: refs/heads/master]` alors que la branche par défaut du dépôt wiki est autre (ex. `prod`), cest un bug connu de certaines versions de Gitea (lAPI suppose `master`). Contournements possibles : (1) **mettre à jour Gitea** (correctif dans les versions récentes, ex. PR #34244) ; (2) **changer la branche par défaut du wiki** en `master` dans les réglages du dépôt (Settings → Branches). Variable optionnelle `GITEA_WIKI_REF=master` (défaut si wiki configuré sur master).
### Migration docs/ → wiki
**Décision :** tout le contenu de `docs/` (racine du dépôt) est migré vers le wiki ; pas de CI sur le wiki.
**Script de migration :**
| Script | Usage | Description |
|--------|--------|-------------|
| `wiki-migrate-docs.sh` | `./gitea-issues/wiki-migrate-docs.sh [--dry-run] [fichier.md ...]` | Migre `docs/*.md` vers le wiki. `--dry-run` affiche le mapping sans appel API. Si des fichiers sont passés en argument, migre uniquement ceux-là. |
| `wiki-put-page.sh` | `./gitea-issues/wiki-put-page.sh <page_name> <file_path>` | Met à jour ou crée une page wiki à partir dun fichier local (ex. `Home docs/README.md`). |
| `wiki-get-page.sh` | `./gitea-issues/wiki-get-page.sh <page_name>` | Affiche le markdown brut dune page wiki (pour scripts ou agents). |
**Correspondance fichier → page wiki :** nom de fichier sans `.md`, `_` remplacé par `-`, title-case par segment. Ex. OPERATIONS.md → Operations, README.md → Readme.
Les 17 fichiers de `docs/` ont été migrés ; les pages sont visibles sur https://git.4nkweb.com/4nk/lecoffre_ng/wiki. La page **Home** contient le contenu de `docs/README.md` (index et correspondance). **`docs/` est exclu du versionnement** (`.gitignore`) : maintenir `docs/` localement (ne pas le supprimer), pousser les modifications vers le wiki avec `wiki-migrate-docs.sh` ou `wiki-put-page.sh` ; ne pas committer `docs/`.
### Après un clone
Le répertoire `docs/` n'est pas versionné. Pour disposer d'une copie locale (édition puis synchro wiki), recréer le contenu à partir du wiki : ex. `./gitea-issues/wiki-get-page.sh Home > docs/README.md`, ou créer les fichiers manuellement à partir des pages wiki listées dans la section Migration ci-dessus.
### Usage « wiki uniquement » pour les agents
La connaissance du projet peut reposer **uniquement sur le wiki** (sans lire `docs/`) : les agents peuvent exécuter `./gitea-issues/wiki-get-page.sh <PageName>` pour récupérer le contenu markdown dune page et lutiliser comme référence. Exemples : `./gitea-issues/wiki-get-page.sh Home`, `./gitea-issues/wiki-get-page.sh Operations`, `./gitea-issues/wiki-get-page.sh Code-Standards`. Prérequis : token Gitea (comme pour les autres scripts wiki). Les agents peuvent ainsi consulter la doc projet à la demande depuis le wiki, sans dépendre des fichiers locaux `docs/`.
## Agents (commandes)
- **/agent-loop** (`agent-loop.md`) : lance les 2 boucles (récupération + traitement) en arrière-plan ou exécute x cycles (récupération 1 fois puis traitement 1 fois). À la fin d'une boucle de récupération, la boucle traitement lance gitea-issues-process sur les mails reçus.
- **/gitea-issues-process** (`gitea-issues-process.md`) : traite les issues Gitea et les mails en attente (workflow script au maximum, /fix ou /evol, /push-by-script). Voir le fichier de l'agent pour le workflow exact.
## Référence
- Wiki : https://git.4nkweb.com/4nk/lecoffre_ng/wiki
- Documentation opérationnelle (ex. `docs/OPERATIONS.md`) : page wiki **Operations** (après migration).