chore(tickets): sync store local — #307 QA verte finale backend+frontend, merge develop e1dbe56 (branche fix/307-startup-ghost-states-reconciliation commit 57cf825), carnet v7 section Git; AppImage rebuild 14:21 déjà formalisée v0.46.0 (commit dédié 99b400a + tag annoté, artefact sha256 vérifié identique au contenu develop post-merge — pas de nouveau tag); tickets 299-307 + index/counter + #296 carnet/issue; attachments/ et scripts/ hors périmètre; aucun push

This commit is contained in:
2026-09-10 17:32:14 +02:00
parent e1dbe56d9c
commit ca1a27a2b9
22 changed files with 1781 additions and 6 deletions

View File

@ -0,0 +1,189 @@
---
issueRef: "#305"
version: 4
updatedBy: {"kind":"agent","agent_id":"a6c6ea12-bfc6-4bdc-8031-324102dfa34d"}
updatedAt: 1789024612856
---
# Carnet #305 - Tâches planifiées projet avec outil MCP et menu utilisateur
## Demande
- Date: 2026-09-10.
- Ajouter des tâches planifiées liées au projet, gérées par IdeA plutôt que par le cron Linux.
- Les agents doivent disposer d'un tool MCP pour créer des tâches récurrentes/projet.
- L'utilisateur doit disposer d'un menu par projet pour créer, supprimer et modifier ces tasks.
- Motivation: un projet a grossi build après build; l'orchestrateur a créé un cron Linux pour nettoyer régulièrement le dossier. Objectif: permettre cette automatisation dans IdeA, scoped au projet et visible/gérable.
- Après livraison et QA: rebuild AppImage demandé.
## Contraintes initiales
- Les tâches sont liées au projet, pas au système global Linux.
- L'utilisateur doit pouvoir voir/modifier/supprimer ce que les agents créent.
- Le tool MCP doit éviter que les agents contournent IdeA avec `crontab` système.
- Sécurité: commandes planifiées potentiellement destructrices; besoin de permissions/sandbox claires.
- Réutiliser le modèle background tasks pour les exécutions si pertinent, mais distinguer tâche planifiée et exécution ponctuelle.
## Cadrage UX
Surface:
- Ajouter l'entrée `Tâches planifiées` dans le menu du projet.
- Surface unique pour les tâches créées par l'utilisateur et celles demandées par un agent.
- Ligne: état, nom, fréquence, prochaine exécution, résultat dernière exécution, origine (`Créée par vous` ou `Créée par {agent}`), menu `Modifier`, `Exécuter maintenant`, `Suspendre/Reprendre`, `Supprimer`.
- États visibles: `À approuver`, `Active`, `Suspendue`, `En cours`, `Échec`, `Projet inaccessible`.
- État vide: `Aucune tâche planifiée pour ce projet` puis `Créez une tâche pour automatiser une commande récurrente sans utiliser le cron du système.`
Création/édition:
- Action principale: `Nouvelle tâche planifiée`.
- Champs: `Nom`, `Commande`, `Dossier de travail` relatif au projet par défaut, `Planification` (presets `Toutes les heures`, `Chaque jour`, `Chaque semaine`, option `Personnalisée`), `Fuseau horaire`, `Limite de durée`, `Permissions et sandbox`, `Activée`.
- Avant activation: récapitulatif commande exacte, dossier, fréquence, prochaine exécution, permissions accordées.
- Modification de commande/périmètre/planification/permissions repasse par validation.
- Tâche créée par agent: état `À approuver`, ne s'exécute jamais silencieusement. Fiche: `Demandée par {agent}`, date et motif, commande/fréquence proposées, permissions nécessaires, actions `Approuver et activer`, `Modifier avant d’activer`, `Refuser`.
- Le tool MCP doit retourner cet état à l'agent, sans prétendre que la tâche est active.
Sécurité UX:
- Périmètre projet et profil sandbox toujours visibles.
- Accès hors projet, réseau ou commandes potentiellement destructrices signalés explicitement.
- Alerte: `Cette tâche pourra modifier ou supprimer des fichiers automatiquement.`
- Activation initiale d'une tâche demandée par agent exige confirmation utilisateur.
- Toute augmentation de permissions remet la tâche en état `À approuver`.
- `Exécuter maintenant` utilise exactement les permissions planifiées.
- Suppression active: confirmation `Supprimer définitivement cette tâche planifiée ?`.
- Si exécution en cours: choix séparés `Supprimer après l’exécution` et `Arrêter puis supprimer`; ne jamais interrompre implicitement.
Exécutions:
- Fiche: dernière/prochaine exécution, déclenchement `Planifié` ou `Manuel`, début, durée, code sortie, statut, stdout/stderr, permissions réellement utilisées, lien vers la tâche de fond correspondante.
- Succès silencieux.
- Échec: indicateur dans menu projet + notification discrète `Voir les détails`, sans avalanche de notifications répétées.
- IdeA doit indiquer que l'application doit fonctionner pour déclencher les tâches.
- Occurrences manquées pendant arrêt: pas de rattrapage en rafale; seule la prochaine occurrence future est programmée.
- Projet inaccessible: exécution `Ignorée — projet inaccessible`, sans lancer ailleurs.
## Cadrage Architect
Décision:
- Backend + frontend + docs.
- `BackgroundTask` est réutilisé uniquement pour les runs.
- Une tâche planifiée est un nouvel agrégat durable distinct: intention récurrente; chaque déclenchement crée une `BackgroundTask`.
Source de vérité:
- `<app_data_dir>/scheduled-project-tasks/<projectId>.json`.
- Ne pas utiliser `cron`, `systemd timer`, ni fichier auto-exécuté dans le repo.
- Machine-local et IdeA-owned pour éviter qu'un clone embarque une tâche destructrice.
Modèle domaine cible:
```ts
ScheduledProjectTask {
id: ScheduledTaskId
projectId: ProjectId
name: string
description?: string
enabled: boolean
command: { command: string; args: string[]; cwd?: string }
schedule: Interval | Daily | Weekly
timezone: string
nextRunAtMs: number | null
lastRunAtMs?: number
lastTaskId?: TaskId
createdBy: Human | Agent { agentId }
updatedBy: Human | Agent { agentId }
createdAtMs: number
updatedAtMs: number
auditRevision: number
}
```
V1 schedule borné:
- `interval { everyMinutes }`, minimum configurable, défaut min 5 ou 15 minutes.
- `daily { time: "HH:mm" }`.
- `weekly { days: [...], time: "HH:mm" }`.
- Pas de cron expression libre en V1.
Séparation schedule/run:
- `ScheduledProjectTask` = définition visible, éditable, activable/désactivable.
- `ScheduledTaskRun` optionnel = historique léger (`scheduleId`, `taskId`, `plannedAtMs`, `startedAtMs`, `status`).
- `BackgroundTask` = exécution concrète, sortie attachable, cancel/retry existants.
- Préférence architect: champ additif `origin: Scheduled { scheduledTaskId, plannedAtMs } | Manual` sur les runs/background tasks, plutôt que mélanger la nature et la provenance.
Ports/use cases:
- `ScheduledProjectTaskStore`: `list(projectId)`, `get(projectId, scheduleId)`, `save(task)`, `delete(projectId, scheduleId)`, `list_due(nowMs)`.
- `ScheduledProjectTaskAuditStore` ou audit via event store existant.
- `ProjectTaskScheduler`: `reconcile_project(projectId)`, `arm(scheduleId, nextRunAtMs)`, `cancel(scheduleId)`.
- Use cases: `ListScheduledProjectTasks`, `CreateScheduledProjectTask`, `UpdateScheduledProjectTask`, `DeleteScheduledProjectTask`, `RunScheduledProjectTaskNow`, `ReconcileScheduledProjectTasks`, `FireScheduledProjectTask`.
- `FireScheduledProjectTask`: calcule prochain run, persiste avant spawn, puis appelle `SpawnBackgroundCommand` avec `wakePolicy = RecordOnly` par défaut.
Scheduler/boot:
- Réutiliser `TokioScheduler` one-shot comme mécanisme de réveil, jamais comme source de vérité.
- Au boot: charger projets connus; pour chaque projet ouvert/restauré, `reconcile_project(projectId)`.
- V1: ne pas lancer de tâches pour projets fermés.
- Si `nextRunAtMs <= now`: politique `skipMissedAndScheduleNext`, pas de rafale.
- Si une run était `Running` avant crash: laisser le reconcile `BackgroundTask` existant marquer failed/lost handle.
Sécurité:
- `cwd` confiné au project root.
- Pas d'`env` libre V1, ou seulement références à variables existantes; jamais de secrets persistés.
- Commande/args visibles intégralement avant activation.
- Audit create/update/delete/enable/disable/runNow: actor, projectId, scheduleId, diff résumé, timestamp.
- Tools MCP création/modification/suppression = `WriteAction`, soumis aux permissions MCP natives.
- #305 fournit l'alternative visible au cron système; limiter les permissions shell/sandbox reste nécessaire pour empêcher un agent large de lancer `crontab` directement.
MCP tools à ajouter:
- `idea_scheduled_task_list` read-only
- `idea_scheduled_task_read` read-only
- `idea_scheduled_task_create` write-action
- `idea_scheduled_task_update` write-action
- `idea_scheduled_task_delete` write-action
- `idea_scheduled_task_run_now` write-action
- `idea_scheduled_task_set_enabled` write-action
- Project scope vient du serveur MCP du projet courant; l'agent ne choisit pas un autre projectId.
DTO/API Tauri + HTTP:
- `list_scheduled_project_tasks(projectId)`
- `create_scheduled_project_task(request)`
- `update_scheduled_project_task(request)`
- `delete_scheduled_project_task(projectId, scheduledTaskId)`
- `run_scheduled_project_task_now(projectId, scheduledTaskId)`
- `set_scheduled_project_task_enabled(projectId, scheduledTaskId, enabled)`
- DTO camelCase: `nextRunAtMs`, `lastRunAtMs`, `lastTaskId`, `createdBy`, `updatedBy`.
Frontend:
- Nouvelle surface projet/menu `Tâches planifiées`.
- `ScheduledTaskGateway` dans ports/adapters Tauri/HTTP/mock.
- Panneau liste + create/edit/delete/enable/run-now.
- Lien vers `BackgroundTask` du dernier run si `lastTaskId` existe.
- Ne pas fusionner avec WorkState: WorkState montre les runs; panneau planifié montre les définitions.
Docs:
- Mettre à jour la doc MCP/agent-facing pour `idea_scheduled_task_*`.
- `sdk/IdeaSDK/docs/services.md` si exposé aux plugins, sinon préciser que ce n'est pas un service plugin V1.
- `sdk/IdeaSDK/docs/manifest.md` seulement si contributions plugin touchent les schedules, déconseillé V1.
- Mentionner explicitement: ne pas utiliser cron système pour une maintenance projet IdeA.
Fichiers probables:
- Backend: `crates/domain/src/scheduled_task.rs`, `crates/domain/src/ports.rs`, `crates/application/src/scheduled_task/mod.rs`, `crates/application/src/background/mod.rs`, `crates/infrastructure/src/store/scheduled_task.rs`, `crates/infrastructure/src/scheduler/mod.rs`, `crates/backend/src/lib.rs`, `crates/app-tauri/src/commands.rs`, `crates/backend/src/dto.rs`, `crates/web-server/src/lib.rs`, `crates/infrastructure/src/orchestrator/mcp/tools.rs`.
- Frontend: `frontend/src/features/scheduled-tasks/*`, `frontend/src/ports/index.ts`, `frontend/src/adapters/scheduledTask.ts`, `frontend/src/adapters/http/requestResponseGateways.ts`, `frontend/src/adapters/mock/index.ts`, `frontend/src/features/projects/ProjectsView.tsx`, `frontend/src/features/web/webSurfaceCatalog.ts`.
## Critères QA
- Une tâche utilisateur et une tâche créée via MCP apparaissent dans la même liste.
- L'auteur, commande, fréquence, prochaine exécution et permissions sont identifiables.
- Tâche demandée par agent ne s'exécute pas avant approbation.
- Approuver/refuser/modifier/suspendre/reprendre/supprimer produisent les états attendus.
- Modification sensible redemande une approbation.
- Tâche suspendue ne s'exécute pas.
- Exécution manuelle et planifiée sont distinguables/auditables.
- Logs, durée, code de sortie et erreurs consultables.
- Projet inaccessible ne bloque pas IdeA et ne déplace jamais l'exécution ailleurs.
- Aucun rattrapage multiple après arrêt prolongé.
- Suppression pendant exécution ne l'interrompt pas sans choix explicite.
- Succès silencieux; échecs visibles sans notifications répétitives.
- Horaires respectent le fuseau configuré.
- Créer via MCP puis vérifier UI; créer/modifier/supprimer via UI puis vérifier MCP list/read.
- Échéance atteinte: `BackgroundTask` créée, visible WorkState, sortie attachable.
- Redémarrage avant échéance: reconcile rearme.
- Redémarrage après échéance manquée: pas de rafale, prochaine échéance recalculée, audit missed/skipped.
- Projet fermé: aucune exécution silencieuse.
- `cwd` hors projet rejeté.
- Tool MCP write refusé sans permission native.
- Delete/disable annule le timer armé.
- Deux reconciles concurrents ne créent pas deux runs pour la même échéance.
## Blocage — 2026-09-10
- Git a préparé `feature/305-scheduled-project-tasks-mcp`, mais a recommandé de finaliser #304 avant de démarrer #305.
- #304 est implémenté et QA vert, mais non committé/mergé: trois délégations Git pour le commit/merge #304 ont expiré à 600s malgré relance/rattachement.
- Le worktree courant porte encore les deux fichiers frontend #304 modifiés. Main ne doit pas démarrer #305 ni changer de branche tant que cette topologie n'est pas résolue, pour éviter de mélanger les changements.
- Prochaine reprise: débloquer Git ou faire exécuter par l'agent Git le commit/merge #304, puis checkout/rebase/reset de `feature/305-scheduled-project-tasks-mcp` par Git et lancer DevBackend #305.