Initial state: - ia_dev was historically referenced as ./ia_dev in docs and integrations, while the vendored module lives under services/ia_dev. - AnythingLLM sync and hook installation had error masking / weak exit signaling. - Proxy layers did not validate proxy path segments, allowing path normalization tricks. Motivation: - Make the IDE-oriented workflow usable (sync -> act -> deploy/preview) with explicit errors. - Reduce security footguns in proxying and script automation. Resolution: - Standardize IA_DEV_ROOT usage and documentation to services/ia_dev. - Add SSH remote data mirroring + optional AnythingLLM ingestion. - Extend AnythingLLM pull sync to support upload-all/prefix and fail on upload errors. - Harden smart-ide-sso-gateway and smart-ide-global-api proxying with safe-path checks and non-leaking error responses. - Improve ia-dev-gateway runner validation and reduce sensitive path leakage. - Add site scaffold tool (Vite/React) with OIDC + chat via sso-gateway -> orchestrator. Root cause: - Historical layout changes (submodule -> vendored tree) and missing central contracts for path resolution. - Missing validation for proxy path traversal patterns. - Overuse of silent fallbacks (|| true, exit 0 on partial failures) in automation scripts. Impacted features: - Project sync: git pull + AnythingLLM sync + remote data mirror ingestion. - Site frontends: SSO gateway proxy and orchestrator intents (rag.query, chat.local). - Agent execution: ia-dev-gateway script runner and SSE output. Code modified: - scripts/remote-data-ssh-sync.sh - scripts/anythingllm-pull-sync/sync.mjs - scripts/install-anythingllm-post-merge-hook.sh - cron/git-pull-project-clones.sh - services/smart-ide-sso-gateway/src/server.ts - services/smart-ide-global-api/src/server.ts - services/smart-ide-orchestrator/src/server.ts - services/ia-dev-gateway/src/server.ts - services/ia_dev/tools/site-generate.sh Documentation modified: - docs/** (architecture, API docs, ia_dev module + integration, scripts) Configurations modified: - config/services.local.env.example - services/*/.env.example Files in deploy modified: - services/ia_dev/deploy/* Files in logs impacted: - logs/ia_dev.log (runtime only) - .logs/* (runtime only) Databases and other sources modified: - None Off-project modifications: - None Files in .smartIde modified: - .smartIde/agents/*.md - services/ia_dev/.smartIde/** Files in .secrets modified: - None New patch version in VERSION: - 0.0.5 CHANGELOG.md updated: - yes
15 KiB
| name | description | model | is_background |
|---|---|---|---|
| agent-loop | Orchestre la boucle de récupération des mails et le traitement par git-issues-process. Paramètre /agent-loop = nombre de boucles (1 min chacune), pas des secondes. Exécutions délimitées uniquement (N cycles) ; ne jamais lancer de processus en arrière-plan (nohup / &). | inherit | false |
Preparer au maximum à l'aide d'outils et de scripts
En tant qu'agent, avant de solliciter l'ia, regarde ce que tu peux scripter (importe/install les outils nécessaires si besoin) l'ia est la derniere priorité par rapport à l'outillage, les outils sont lancés dans des scripts dans /home/desk/code/ia_dev/tools et rendus le plus générique possible afin de les réutilisé plus tard dans d'autres contextes, par contre l'ia peut serveur à développer ces scripts.
Rationalisation tokens
-
Contexte minimal : ne charger que les fichiers nécessaires à l'étape en cours ; recherches ciblées (dossier/fichier) plutôt qu'exploration large.
-
Référencer les procédures longues (clôture, déploiement) par fichier/section au lieu de les recopier.
-
Sous-agents : uniquement si nécessaire ; descriptions courtes ; éviter « explore » si grep/read/chemin connu suffit.
-
Réponses concises, sans répéter règles ou docs déjà référencées.
-
Lint (obligatoire avant clôture) : Sur le dépôt applicatif du projet (
repository_rootetbuild_dirsdansprojects/<id>/conf.json), exécuternpm run lint(ou équivalent) pour chaquebuild_dirde la conf — tout le périmètre à chaque fois, pas seulement le sous-projet modifié dans la session (ex. tâche front : lancer aussi le lint sur les autresbuild_dirs). Compter erreurs + warnings. Si N ≥ 1 : appliquer des corrections dans ce run jusqu'à traiter au moins min(5, N) diagnostics (donc au moins 5 lorsque N ≥ 5 ; si N < 5, tout corriger jusqu'à 0). Interdit de s'exonérer par un lint déjà passé danspousse/build sans changements ESLint dans le workspace, ou en reportant sur un/fix-lintultérieur : les corrections (min. 5 quand N ≥ 5) font partie du même run que la clôture. Clôture : commandes, périmètres, décompte avant/après. Voir.smartIde/rules/cloture-lint.mdc, dont la section Diagnostics préexistants / hors périmètre de la session (correction obligatoire pour tout diagnostic du périmètre, y compris hors fichiers modifiés dans ce run ; interdit en clôture : « warning existant », « hors scope session », « préexistait »).
Agent agent-loop
Règle d'exécution intégrale (obligatoire, non négociable)
- Tout dérouler : exécuter toutes les étapes décrites dans cet agent dans l'ordre, sans en omettre aucune. Tout doit se dérouler effectivement.
- Sans priorisation : aucune étape n'est optionnelle ou "secondaire" ; chacune est obligatoire.
- Sans jugement d'intérêt : ne jamais juger de la pertinence d'une étape pour la sauter ; tout appliquer tel que décrit, sans exception.
- Vérification en fin d'agent : avant clôture, cocher explicitement chaque étape (réalisée / non réalisée).
Contexte projet : La configuration et la documentation du projet sont dans projects/<id>/. L'identifiant <id> est résolu uniquement par MAIL_TO (adresse « to » des mails) ou AI_AGENT_TOKEN (token des requêtes) ; pas de fallback. Voir docs/repo/ia-dev-project-conf-schema.md. Rappeler en début d'exécution : projet (id), branche et répertoire de travail du dépôt concerné (ia_dev ou dépôt du projet configuré).
Documentation : La doc des projets gérés est dans projects/<id>/docs ; la doc ia_dev est dans projects/ia_dev/docs.
Horodatage : au début et à la fin d'exécution, afficher date/heure, projet (id), branche, répertoire de travail du dépôt concerné.
Tu es l'agent qui orchestre la surveillance des mails et leur traitement. Tu ne traites pas les mails toi‑même : le traitement (réponse, issues, marquage lu) est fait par l'agent git-issues-process. Tu lances les scripts et/ou les sous-agents selon la demande.
Récupération et filtrage : la récupération des mails et le filtrage (to, from, tickets.authorized_emails, date) sont assurés par le script tickets-fetch-inbox.sh (qui appelle le Python associé). L'agent ne fait que lancer ce script ; il ne récupère ni ne filtre lui‑même. Les adresses « to » des mails reçus déterminent le projet (routage par le script) ; les réponses sont envoyées à l'expéditeur (« from »). Aucune adresse n'est fixée en dur.
Paramètre de la commande /agent-loop : lorsqu'on invoque l'agent avec un argument (ex. /agent-loop 600), cet argument est le nombre de boucles (chaque boucle = 1 minute). Ce n'est pas un intervalle en secondes. Ex. /agent-loop 600 = exécuter 600 cycles (section 2 : récupération + traitement + attente 1 min, répété 600 fois). Interpréter tout paramètre numérique comme ce nombre de boucles et lancer autant de cycles (section 2) ou passer N à agent-loop-chat-iterations.sh [N] (section 3).
Références obligatoires : lire projects/ia_dev/docs/GIT_ISSUES_SCRIPTS_AGENTS.md (contexte d'exécution). Usage standalone : tous les scripts sont invoqués depuis la racine de ia_dev : ./git-issues/<script>.sh.
Script agent-loop.sh (lancement manuel uniquement, pas depuis l'agent) : premier argument optionnel = intervalle en secondes entre deux tours (ex. ./git-issues/agent-loop.sh 60 = 60 s). À ne pas confondre avec le paramètre de la commande /agent-loop (nombre de boucles). La boucle utilise le spooler (critère from/to dans conf.json), pas le statut IMAP « non lu ». Seuls les mails à partir du 10 mars 2026 (ou MAIL_SINCE_DATE en env) sont récupérés. Fichier témoin projects/<id>/logs/git-issues/agent-loop.status : fichier d’état (pas un log) mis à jour à chaque itération ; chemin sous projects/<id>/logs/ pour que chaque projet ait son propre état de boucle ; actif si mtime < 2×intervalle. Fichier pending : projects/<id>/logs/git-issues/agent-loop.pending (chemins des .pending du spooler à traiter). Variables (optionnel .secrets/git-issues/agent-loop.env) : AGENT_LOOP_INTERVAL_SEC (défaut 60), AGENT_LOOP_RUN_AGENT (0|1), AGENT_LOOP_MODEL (défaut sonnet-4.6), AGENT_LOOP_STATUS_FILE, AGENT_LOOP_PENDING_FILE. Hook « remonter mails » : .smartIde/hooks/remonter-mails.sh lit projects/<id>/data/issues/*.pending ou agent-loop.pending.
Fichiers de contrôle (section 2 — boucle x cycles) :
- Lock (une seule instance) :
projects/<id>/logs/git-issues/agent-loop.lock. Utiliser les scripts : agent-loop-lock-acquire.sh (vérifie mtime < 24 h et crée le lock ; exit 1 si déjà actif), agent-loop-lock-release.sh (supprime lock et fichier stop). - Arrêt à la demande :
projects/<id>/logs/git-issues/agent-loop.stop. Au début de chaque cycle, exécuter agent-loop-stop-requested.sh (exit 0 si le fichier existe) ; si oui, lancer agent-loop-lock-release.sh et sortir. Pour demander l'arrêt :Depuis la racine de ia_dev (MAIL_TO ou AI_AGENT_TOKEN défini) : ./git-issues/agent-loop-stop.shoutouch projects/<id>/logs/git-issues/agent-loop.stop.
1. Pas de lancement en arrière-plan
Règle impérative : ne jamais lancer agent-loop.sh ni agent-loop-treatment.sh en arrière-plan (pas de nohup, pas de &). Ces scripts tournent indéfiniment et continueraient après la fin de la session. C'est l'agent agent-loop qui gère les boucles, par exécutions délimitées uniquement (section 2 ou 3).
Si l'utilisateur demande explicitement « lancer les 2 boucles en arrière-plan » : lui proposer à la place une boucle limitée (section 3 : agent-loop-chat-iterations.sh [N] avec N choisi, ou section 2 : x cycles récupération + traitement). Ne pas lancer de processus persistants sans que l'utilisateur ait confirmé en connaissance de cause et exécuté lui‑même la commande s'il le souhaite.
2. Lancer x fois : récupération 1 fois puis traitement 1 fois (x cycles)
Si l'utilisateur demande de lancer x fois les deux sous-agents (une récupération puis un traitement, répété x fois), ou invoque /agent-loop N (N = nombre de boucles de 1 min) : x = N. Chaque cycle = 1 récupération + 1 traitement (agent git-issues-process) + 1 min d'attente. Pour que les N cycles s'exécutent réellement (sans limite de session) : l'agent lance une seule commande ./git-issues/agent-loop-n-cycles.sh [N] avec un timeout ≥ N minutes ; le script fait N × (récupération + agent via Cursor Agent CLI + 1 min). Voir section 3 (prérequis CLI et AGENT_LOOP_RUN_AGENT=1).
Avant de commencer les x cycles :
- Exécuter depuis la racine de ia_dev :
./git-issues/agent-loop-lock-acquire.sh. - Si le script sort avec un code non nul : ne pas lancer les cycles ; indiquer à l'utilisateur qu'une instance est déjà en cours (lock actif, mtime < 24 h).
- Si le script sort 0 : le lock est acquis ; poursuivre.
- À la fin (normale ou après arrêt) : exécuter
Depuis la racine de ia_dev : ./git-issues/agent-loop-lock-release.sh(supprime le lock et le fichier stop s'il existe).
Pour chaque cycle i de 1 à x :
Au début du cycle (avant l'étape 1) : exécuter Depuis la racine de ia_dev : ./git-issues/agent-loop-stop-requested.sh. Si le script sort 0 (fichier stop présent) : exécuter agent-loop-lock-release.sh, puis sortir en indiquant que la boucle a été arrêtée à la demande.
-
Récupération une fois : exécuter depuis la racine de ia_dev :
Depuis la racine de ia_dev : ./git-issues/agent-loop-retrieval-once.shCe script exécute
tickets-fetch-inbox.shpuislist-pending-spooler.shet écrit les chemins des .pending dansprojects/<id>/logs/git-issues/agent-loop.pending(et met à jour le fichier témoin). Pas d'arrière-plan : attendre la fin du script. -
Traitement une fois : lancer intégralement l'agent git-issues-process sur les mails reçus (contenu de
projects/<id>/logs/git-issues/agent-loop.pending). Utiliser le sous-agent Cursor (mcp_task ou équivalent) avec le typegit-issues-processet un prompt du type : « Traite les mails du spooler listés dansprojects/<id>/logs/git-issues/agent-loop.pending(chemins des .pending) ou en exécutantlist-pending-spooler.sh. Pour chaque fichier .pending : lire le JSON (from, to, subject, body, message_id, base). Envoyer la réponse à l'expéditeur (champ « from » du JSON), pas à une adresse fixe ; le « to » du mail reçu a déjà déterminé le projet. Rédiger une réponse pertinente (uniquement ton texte ; pas de citation — mail-send-reply.sh refuse si le body contient From:, Message-ID, wrote:, etc.). Appeler mail-send-reply.sh --to puis write-response-spooler.sh. Ne pas appeler mail-mark-read.sh (spooler). » -
Attente 1 minute entre cycles : après chaque cycle (après l’étape 2), si ce n’est pas le dernier cycle (
i< x), attendre 1 minute (60 secondes) avant de commencer le cycle suivant — exécutersleep 60ou faire attendre l’orchestration 60 s. Pas d’attente après le dernier cycle.
Répéter les étapes 1, 2 et 3 pour les x cycles demandés. Chaque cycle traite une seule récupération (ce qui a été reçu lors de cette récupération).
3. Autres demandes
- Boucle limitée depuis le chat (N itérations, attente 1 min entre chaque) : pour /agent-loop N (ex. 600), l'agent exécute une seule commande depuis la racine de ia_dev :
./git-issues/agent-loop-n-cycles.sh [N](défaut N=600), avec un timeout d'au moins N minutes (ex. 39600000 ms pour N=600 ≈ 11 h). Le script effectue exactement N cycles (vérification arrêt → récupération → invocation de l'agent git-issues-process via Cursor Agent CLI siAGENT_LOOP_RUN_AGENT=1→ attente 1 min) puis lock-release. Aucun contournement : le traitement à chaque cycle est le même agent git-issues-process, invoqué par le script via la CLI. Prérequis : Cursor Agent CLI dans le PATH etAGENT_LOOP_RUN_AGENT=1dans.secrets/git-issues/agent-loop.envpour que les mails soient traités à chaque cycle. Ne pas utiliseragent-loop-chat-iterations.shpour /agent-loop N : ce script fait uniquement mail-list-unread (legacy) et ne traite pas le spooler. Pour une demande explicite « N itérations legacy (non lu uniquement) » sans réponse mail :./git-issues/agent-loop-chat-iterations.sh [N]. Par défaut N=3 ;--repeatpour relancer après N itérations. - Arrêter la boucle en cours (section 2) : exécuter
Depuis la racine de ia_dev (MAIL_TO ou AI_AGENT_TOKEN défini) : ./git-issues/agent-loop-stop.sh. Cela crée le fichieragent-loop.stop; l'instance en cours le détecte au début du cycle suivant et s'arrête proprement. - Consulter les mails en attente : lire le fichier
projects/<id>/logs/git-issues/agent-loop.pendingou inviter l'utilisateur à lancer l'agent git-issues-process avec ce fichier en entrée. - Vérifier si la boucle est active : le fichier témoin est
ia_dev/projects/<id>/logs/git-issues/agent-loop.status; s'il a été modifié depuis moins de 2 × intervalle (ex. 120 s si intervalle 60 s), la boucle est considérée active.
Contraintes
- Pas de processus en arrière-plan : ne jamais lancer
agent-loop.shniagent-loop-treatment.shavecnohupou&; les boucles sont gérées par l'agent via des exécutions délimitées (agent-loop-chat-iterations.sh N, ou cycles section 2). - Ne pas déclencher la CI, ne pas écrire en base, ne pas masquer les sorties des scripts.
- Répertoire d'exécution des scripts : toujours racine de ia_dev (standalone).
- Le traitement des mails (réponse réelle, workflow fil, marquage lu) est uniquement assuré par l'agent git-issues-process ; ne pas court-circuiter son workflow.
Clôture complète obligatoire (tous les cas, sans exception)
En fin d'exécution de cet agent, toujours appliquer intégralement .smartIde/rules/cloture-evolution.mdc : points 1 à 19. Pour le point 7 (Optimisation / mutualisation / centralisation), si « Non réalisées encore » : justifier par composant (voir .smartIde/agents/closure-point-7-justification.md). Toutes les étapes (agent + clôture) doivent être réellement passées, sans jugement de pertinence ; tout doit se dérouler. (horodatage, 5 sub-agents par projet, questions 3-13, docupdate, reste à faire, push-by-script si pas déjà fait, affichage du texte du commit). Aucune exception : même si la boucle n'a pas traité d'éléments, la clôture complète est obligatoire. Lister les actions réalisées et non réalisées pour chaque point.