1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
# Multi-Agent System 2.0 Design
**Goal:** Replace the current bash-script based worker system (`start-worker.sh`, etc.) with a robust, type-safe Haskell application `Omni/Agent.hs`.
## 1. CLI Interface
The `agent` command (compiled from `Omni/Agent.hs`) will provide a unified interface for managing workers.
```bash
agent start <name> [--background] # Start a worker (foreground by default, background with flag)
agent stop <name> # Stop a background worker
agent status # List all workers and their status
agent log <name> [-f] # View/tail worker logs
agent harvest # Harvest task updates from all workers
agent sync # Sync local state with live (helper)
```
## 2. Module Structure (`Omni/Agent/`)
We will refactor the bash logic into Haskell modules:
- **Omni.Agent** (`Omni/Agent.hs`): Main entry point and CLI parsing (Docopt).
- **Omni.Agent.Core**: Core data types and state management.
- **Omni.Agent.Worker**: The worker loop logic (sync, claim, work, submit).
- **Omni.Agent.Git**: Git operations (worktree, branch, merge, commit).
- **Omni.Agent.Process**: Process management (PID files, signals).
- **Omni.Agent.Log**: Log streaming and filtering (the "monitor" logic).
## 3. Data Types
```haskell
data WorkerStatus
= Idle
| Syncing
| Working TaskId
| Submitting TaskId
| Error Text
deriving (Show, Eq, Generic)
data Worker = Worker
{ workerName :: Text
, workerPid :: Maybe Int
, workerStatus :: WorkerStatus
, workerPath :: FilePath
}
```
## 4. Implementation Details
### 4.1 Worker Loop (`agent start`)
The Haskell implementation should replicate the logic of `start-worker.sh` but with better error handling and logging.
1. **Setup**: Ensure worktree exists (or create it).
2. **Loop**:
- `Git.syncWithLive`
- `Task.sync`
- `task <- Task.findReady`
- If `task`:
- `Task.claim task`
- `Git.checkoutTaskBranch task`
- `Amp.execute prompt`
- `Git.commit`
- `Git.checkoutBase`
- `Task.submitReview task`
- Else: `sleep 60`
### 4.2 Process Management
- Store PIDs in `.tasks/workers/<name>.pid`.
- `agent stop` sends SIGTERM to the PID.
- `agent status` checks if PID is alive.
### 4.3 Logging
- Continue writing raw Amp logs to `_/llm/amp.log` in the worker directory.
- `agent log` reads this file and applies the filtering logic (currently in `monitor-worker.sh` jq script) using Haskell (Aeson).
### 4.4 Harvesting
- Iterate over `.tasks/workers/` or `git worktree list`.
- For each worker, extract `.tasks/tasks.jsonl` via `git show`.
- Run `Task.import`.
## 5. Migration Strategy
1. **Parallel Existence**: Keep bash scripts while developing Haskell version.
2. **Feature Parity**: Ensure `agent start` works exactly like `start-worker.sh`.
3. **Cutover**: Update `WORKER_AGENT_GUIDE.md` to use `agent` command.
4. **Cleanup**: Delete bash scripts.
## 6. Testing Plan
### 6.1 Unit Tests (`Omni/Agent/Test.hs`)
- Test `Git` module commands (mocked).
- Test `Log` filtering logic.
- Test CLI argument parsing.
### 6.2 Integration Tests
- Create a temporary test repo.
- Spawn a worker.
- Mock `amp` binary (simple script that `echo "done"`).
- Verify task moves from Open -> InProgress -> Review.
## 7. References
- `Omni/Agent/start-worker.sh` (Current implementation)
- `Omni/Task.hs` (Task manager integration)
|