Tâches : scripts planifiés sans modèle, et l'IA planifie la sienne

Deux reprises d'AJEAN autour des tâches planifiées.

Dossier de scripts (/data/scripts) : un dossier durable À CÔTÉ de memory,
hors du workspace. Le workspace est jetable — supprimer une discussion
emporte ses fichiers — donc un script qu'on veut garder n'y avait pas sa
place. Le briefing machine l'annonce à l'IA, qui y écrit et y lance ses
scripts normalement.

Tâche « script seul » (Task.Kind/Script) : le planificateur lance le script
sans charger le modèle ni consommer un token, sa sortie devient le
compte-rendu, et l'UI l'affiche comme n'importe quelle tâche. Elle tourne
hors du verrou de génération — d'où un registre à part pour l'afficher « en
cours » et l'arrêter (/api/tasks/stop), et un « tester » qui n'attend ni le
verrou ni le moteur. Sélecteur Consigne IA / Script seul dans la modale.

Outils task_list/create/update/delete : l'IA se donne elle-même rappels et
veilles récurrentes, cloisonnés par projet (dans un projet, elle ne voit et
ne pilote que ses tâches). Le budget du préambule passe de 8600 à 11000
caractères, avec le palier documenté dans le test.

Dossier mémoire réservé à ses outils : bash, write et edit ne le touchent
plus (guardToolOnly*). Un `cat memory/…` contournait l'index MEMORY.md, et
c'est la condition d'un chiffrement de la mémoire à venir.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6CAgoLJzufeA8rZTSpSpY
This commit is contained in:
Claude committed 2026-09-22 13:33:39 +00:00
1 parent 91d1796615
commit 74fb1fc781
17 files changed
+1043 -26

No files matched your search

+23 -2
View File
@@ -31,6 +31,12 @@ type Task struct {
// chantier — une veille « NAS » n'écrit pas dans la mémoire « recettes ». Vide
// sur les tâches d'avant les projets : traitées comme « Générale ».
Project string `json:"project,omitempty"`
// Kind distingue une tâche IA d'une tâche script. Vide ou "agent" = Prompt est
// une consigne exécutée par le modèle (RunAutonomous). "script" = on lance
// directement le script Script du dossier protégé, SANS charger le modèle ni
// consommer de tokens. Le zéro JSON ("") garde le comportement historique (IA).
Kind string `json:"kind,omitempty"`
Script string `json:"script,omitempty"` // pour Kind=="script" : nom du script dans scriptsDir()
// Accès de la tâche. On stocke la NÉGATION (« pas de… ») pour que le zéro JSON
// (tâches créées avant ces champs) garde le comportement historique : accès.
NoMem bool `json:"no_mem"` // true = pas d'accès à la mémoire pour cette tâche
@@ -75,9 +81,11 @@ func listTasks() []Task {
}
// taskProjectOf renvoie le projet d'une tâche, l'absence valant projet par défaut :
// une tâche d'avant les projets ne doit ni disparaître ni changer de mémoire.
// une tâche d'avant les projets ne doit ni disparaître ni changer de mémoire. Un
// projet SUPPRIMÉ depuis retombe de même sur « Générale » : sans ça, la tâche
// restait rattachée à un slug fantôme et n'apparaissait plus dans aucun projet.
func taskProjectOf(t Task) string {
if s := strings.TrimSpace(t.Project); s != "" {
if s := strings.TrimSpace(t.Project); s != "" && projectExists(s) {
return s
}
return defaultProjectSlug
@@ -101,6 +109,19 @@ func tagOrphanTasks(slug string) {
}
}
// listTasksForProject ne renvoie que les tâches rattachées au projet `slug`
// (mêmes tri et résolution que listTasks). Sert à cloisonner les outils task_*
// exposés à l'IA : dans un projet, elle ne voit et ne pilote QUE ses tâches.
func listTasksForProject(slug string) []Task {
var out []Task
for _, t := range listTasks() {
if taskProjectOf(t) == slug {
out = append(out, t)
}
}
return out
}
// getTask lit une tâche par ID. Renvoie false si absente.
func getTask(id string) (Task, bool) {
var t Task