Worktree + Isolamento Task
CollaborazioneIsolate by Directory
Each works in its own directory; tasks manage goals, worktrees manage directories, bound by ID
s01 > s02 > s03 > s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > [ s12 ]
"Ciascuno lavora nella propria directory, senza interferenze" -- i task gestiscono gli obiettivi, i worktree gestiscono le directory, legati da ID.
Problema
A s11, gli agenti possono prendere e completare task autonomamente. Ma ogni task esegue in una directory condivisa. Due agenti che refattorizzano moduli diversi contemporaneamente si scontreranno: l'agente A modifica config.py, l'agente B modifica config.py, le modifiche non staged si mescolano, e nessuno può rollbackare pulitamente.
La bacheca task traccia cosa fare ma non ha opinioni su dove farlo. La soluzione: dai a ogni task la propria directory git worktree. I task gestiscono gli obiettivi, i worktree gestiscono il contesto di esecuzione. Lega loro per ID del task.
Soluzione
Control plane (.tasks/) Execution plane (.worktrees/)
+------------------+ +------------------------+
| task_1.json | | auth-refactor/ |
| status: in_progress <------> branch: wt/auth-refactor
| worktree: "auth-refactor" | task_id: 1 |
+------------------+ +------------------------+
| task_2.json | | ui-login/ |
| status: pending <------> branch: wt/ui-login
| worktree: "ui-login" | task_id: 2 |
+------------------+ +------------------------+
|
index.json (worktree registry)
events.jsonl (lifecycle log)
Macchine di stato:
Task: pending -> in_progress -> completed
Worktree: absent -> active -> removed | kept
Come Funziona
- Crea un task. Persisti prima l'obiettivo.
TASKS.create("Implement auth refactor")
# -> .tasks/task_1.json status=pending worktree=""
- Crea un worktree e lega al task. Passare
task_idfa avanzare automaticamente il task ain_progress.
WORKTREES.create("auth-refactor", task_id=1)
# -> git worktree add -b wt/auth-refactor .worktrees/auth-refactor HEAD
# -> index.json gets new entry, task_1.json gets worktree="auth-refactor"
Il binding scrive stato su entrambi i lati:
def bind_worktree(self, task_id, worktree):
task = self._load(task_id)
task["worktree"] = worktree
if task["status"] == "pending":
task["status"] = "in_progress"
self._save(task)
- Esegui comandi nel worktree.
cwdpunta alla directory isolata.
subprocess.run(command, shell=True, cwd=worktree_path,
capture_output=True, text=True, timeout=300)
- Chiudi. Due scelte:
worktree_keep(name)-- preserva la directory per dopo.worktree_remove(name, complete_task=True)-- rimuovi la directory, completa il task legato, emetti evento. Una chiamata gestisce teardown + completamento.
def remove(self, name, force=False, complete_task=False):
self._run_git(["worktree", "remove", wt["path"]])
if complete_task and wt.get("task_id") is not None:
self.tasks.update(wt["task_id"], status="completed")
self.tasks.unbind_worktree(wt["task_id"])
self.events.emit("task.completed", ...)
- Flusso eventi. Ogni passo del ciclo di vita emette a
.worktrees/events.jsonl:
{
"event": "worktree.remove.after",
"task": { "id": 1, "status": "completed" },
"worktree": { "name": "auth-refactor", "status": "removed" },
"ts": 1730000000
}
Eventi emessi: worktree.create.before/after/failed, worktree.remove.before/after/failed, worktree.keep, task.completed.
Dopo un crash, lo stato si ricostruisce da .tasks/ + .worktrees/index.json su disco. La memoria della conversazione è volatile; lo stato del file è duraturo.
Cosa è Cambiato da s11
| Componente | Prima (s11) | Dopo (s12) |
|---|---|---|
| Coordinamento | Bacheca task (owner/stato) | Bacheca task + binding worktree esplicito |
| Scope esecuzione | Directory condivisa | Directory isolata per task |
| Riparabilità | Solo stato task | Stato task + indice worktree |
| Teardown | Completamento task | Completamento task + keep/remove esplicito |
| Visibilità ciclo | Implicita nei log | Eventi espliciti in .worktrees/events.jsonl |
Provalo
python agents/s12_worktree_task_isolation.py
Crea task per auth backend e pagina login frontend, poi elenca i task.Crea worktree "auth-refactor" per il task 1, poi lega il task 2 a un nuovo worktree "ui-login".Esegui "git status --short" nel worktree "auth-refactor".Mantieni worktree "ui-login", poi elenca i worktree e ispeziona gli eventi.Rimuovi worktree "auth-refactor" con complete_task=true, poi elenca task/worktree/eventi.
