@automagik/genie 3.260310.5 → 3.260314.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/.genie/brainstorms/agent-directory/DESIGN.md +310 -0
  2. package/.genie/brainstorms/agent-directory/DRAFT.md +628 -0
  3. package/.genie/wishes/fix-onboarding-prod-bugs/WISH.md +153 -0
  4. package/.genie/wishes/genie-v2-framework-redesign/WISH.md +546 -0
  5. package/README.md +14 -14
  6. package/dist/genie.js +162 -185
  7. package/docs/CO-ORCHESTRATION-GUIDE.md +92 -122
  8. package/docs/agent-profiles.md +3 -3
  9. package/git-cliff/CHANGELOG.md +45 -0
  10. package/knip.json +3 -1
  11. package/package.json +7 -3
  12. package/report.md +171 -0
  13. package/skills/brainstorm/SKILL.md +9 -2
  14. package/skills/council/SKILL.md +46 -1
  15. package/skills/docs/SKILL.md +4 -7
  16. package/skills/dream/SKILL.md +25 -67
  17. package/skills/fix/SKILL.md +7 -7
  18. package/skills/onboarding/SKILL.md +13 -13
  19. package/skills/report/SKILL.md +5 -6
  20. package/skills/review/SKILL.md +20 -7
  21. package/skills/trace/SKILL.md +4 -7
  22. package/skills/wish/SKILL.md +7 -0
  23. package/skills/work/SKILL.md +28 -51
  24. package/src/genie-commands/__tests__/session.test.ts +5 -6
  25. package/src/genie-commands/session.ts +8 -268
  26. package/src/genie.ts +167 -165
  27. package/src/hooks/__tests__/branch-guard.test.ts +182 -0
  28. package/src/hooks/handlers/auto-spawn.ts +32 -4
  29. package/src/hooks/handlers/branch-guard.ts +70 -0
  30. package/src/hooks/handlers/identity-inject.ts +1 -1
  31. package/src/hooks/inject.ts +2 -2
  32. package/src/lib/agent-directory.test.ts +240 -0
  33. package/src/lib/agent-directory.ts +328 -0
  34. package/src/lib/agent-registry.ts +6 -70
  35. package/src/lib/auto-approve.test.ts +1 -1
  36. package/src/lib/auto-approve.ts +0 -25
  37. package/src/lib/builtin-agents.test.ts +137 -0
  38. package/src/lib/builtin-agents.ts +258 -0
  39. package/src/lib/claude-logs.ts +0 -62
  40. package/src/lib/genie-config.ts +0 -68
  41. package/src/lib/idle-timeout.ts +0 -39
  42. package/src/lib/local-tasks.test.ts +5 -0
  43. package/src/lib/local-tasks.ts +2 -2
  44. package/src/lib/orchestrator/index.ts +0 -1
  45. package/src/lib/orchestrator/state-detector.ts +0 -121
  46. package/src/lib/protocol-router.test.ts +104 -0
  47. package/src/lib/protocol-router.ts +28 -5
  48. package/src/lib/provider-adapters.test.ts +52 -0
  49. package/src/lib/provider-adapters.ts +27 -0
  50. package/src/lib/session-store.ts +82 -0
  51. package/src/lib/spawn-command.test.ts +0 -34
  52. package/src/lib/spawn-command.ts +3 -10
  53. package/src/lib/target-resolver.test.ts +2 -2
  54. package/src/lib/target-resolver.ts +9 -9
  55. package/src/lib/team-chat.test.ts +128 -0
  56. package/src/lib/team-chat.ts +101 -0
  57. package/src/lib/team-lead-command.ts +16 -25
  58. package/src/lib/team-manager.test.ts +232 -0
  59. package/src/lib/team-manager.ts +240 -118
  60. package/src/lib/team-shortcut.test.ts +1 -1
  61. package/src/lib/tmux.ts +1 -234
  62. package/src/lib/wish-state.test.ts +285 -0
  63. package/src/lib/wish-state.ts +297 -0
  64. package/src/lib/worktree-manager.test.ts +1 -44
  65. package/src/lib/worktree-manager.ts +6 -245
  66. package/src/term-commands/agents.ts +209 -667
  67. package/src/term-commands/approve.test.ts +0 -14
  68. package/src/term-commands/approve.ts +1 -103
  69. package/src/term-commands/dir.ts +268 -0
  70. package/src/term-commands/dispatch.test.ts +504 -0
  71. package/src/term-commands/dispatch.ts +407 -0
  72. package/src/term-commands/events.ts +2 -238
  73. package/src/term-commands/history.ts +5 -5
  74. package/src/term-commands/msg.test.ts +154 -23
  75. package/src/term-commands/msg.ts +242 -27
  76. package/src/term-commands/state.ts +161 -0
  77. package/src/term-commands/team.test.ts +148 -0
  78. package/src/term-commands/team.ts +149 -75
  79. package/src/types/genie-config.ts +0 -2
  80. package/src/__tests__/beads-issues-jsonl.test.ts +0 -63
  81. package/src/__tests__/brainstorm-crystallize.test.ts +0 -39
  82. package/src/genie-commands/brainstorm/crystallize.ts +0 -67
  83. package/src/genie-commands/ledger/validate.ts +0 -5
  84. package/src/genie-commands/profiles.ts +0 -204
  85. package/src/lib/beads-issues-jsonl.ts +0 -152
  86. package/src/lib/beads-registry.ts +0 -425
  87. package/src/lib/orchestrator/event-monitor.ts +0 -232
  88. package/src/lib/skill-loader.ts +0 -96
  89. package/src/lib/task-backend.ts +0 -215
  90. package/src/lib/wish-tasks.ts +0 -140
  91. package/src/term-commands/beads-validate.ts +0 -93
  92. package/src/term-commands/brainstorm-beads.ts +0 -59
  93. package/src/term-commands/close.ts +0 -325
  94. package/src/term-commands/council.ts +0 -173
  95. package/src/term-commands/create.ts +0 -64
  96. package/src/term-commands/daemon.ts +0 -177
  97. package/src/term-commands/exec.ts +0 -40
  98. package/src/term-commands/ship.ts +0 -247
  99. package/src/term-commands/task/commands.ts +0 -448
  100. package/src/term-commands/update.ts +0 -113
  101. package/src/term-commands/work.test.ts +0 -775
  102. package/src/term-commands/work.ts +0 -1350
@@ -0,0 +1,310 @@
1
+ # DESIGN: Agent Directory & Multi-Agent Spawn Redesign
2
+
3
+ > Redesign genie's agent spawn and communication system so that pre-existing agents
4
+ > (each with their own home directory, identity files, and project assignments) can be
5
+ > registered once, spawned in one command, and message each other by name.
6
+
7
+ ## Problem
8
+
9
+ `genie agent spawn` creates clones of the spawning agent — they inherit the parent's session context and CLAUDE.md rather than loading their own AGENTS.md identity. Cross-agent messaging requires manual `--team` flags. CWD and identity source are conflated via the `-d` flag. This blocks multi-agent workflows where a PM, Engineer, and QA need independent identities while collaborating on the same project.
10
+
11
+ ## Architecture
12
+
13
+ ### Two Registries, Two Lifecycles
14
+
15
+ ```
16
+ ┌─────────────────────────────┐ ┌─────────────────────────────┐
17
+ │ Agent Directory │ │ Worker Registry │
18
+ │ ~/.genie/agent-directory │ │ ~/.genie/workers.json │
19
+ │ .json │ │ │
20
+ │ │ │ │
21
+ │ WHO the agent IS │ │ HOW to restart it │
22
+ │ - name │ │ - paneId, session │
23
+ │ - home (AGENTS.md src) │ │ - claudeSessionId │
24
+ │ - project (CWD) │ │ - state, team │
25
+ │ - default team │ │ + templates[] for recovery │
26
+ │ │ │ │
27
+ │ Human-configured │ │ Auto-generated at spawn │
28
+ │ Persistent across reboots │ │ Ephemeral (pane lifecycle) │
29
+ │ Source of truth for ID │ │ Source of truth for state │
30
+ └──────────────┬──────────────┘ └──────────────┬──────────────┘
31
+ │ │
32
+ │ 1. spawn resolves identity │ 3. template saved
33
+ │ 2. CWD + prompt injected │ for auto-respawn
34
+ ▼ ▼
35
+ ┌─────────────────────────────────────────────┐
36
+ │ genie agent spawn │
37
+ │ Reads directory → injects identity → │
38
+ │ launches in tmux → registers worker → │
39
+ │ saves template for recovery │
40
+ └─────────────────────────────────────────────┘
41
+ ```
42
+
43
+ ### Key Separations
44
+
45
+ | Concern | Source | Used At |
46
+ |---------|--------|---------|
47
+ | **Identity** (AGENTS.md) | `--home` directory in agent-directory.json | Spawn time → `--append-system-prompt` |
48
+ | **Workspace** (CWD) | `--project` path in agent-directory.json | Spawn time → tmux pane CWD |
49
+ | **Address** | Agent name in directory | Message routing → flat, no `--team` prefix |
50
+ | **Team** | Optional grouping | Tmux window organization, not required for identity or messaging |
51
+ | **Recovery** | WorkerTemplate in workers.json | Auto-respawn on message to dead agent |
52
+
53
+ ## Scope
54
+
55
+ ### IN
56
+ - Persistent agent directory (`~/.genie/agent-directory.json`)
57
+ - `genie agent register <name> --home <path> --project <path>` subcommand
58
+ - `genie agent unregister <name>` subcommand
59
+ - `genie agent directory` subcommand (list all registered agents with status)
60
+ - `genie agent spawn <name>` resolving from directory (positional arg)
61
+ - Identity injection: read AGENTS.md from `--home`, inject via `--append-system-prompt`
62
+ - CWD/identity separation: pane opens at `--project`, identity from `--home`
63
+ - Flat messaging: `genie send --to <name>` resolves via directory without `--team`
64
+ - Auto-spawn on message to offline registered agent
65
+ - Backward compat: `genie agent spawn --role implementor` still works unchanged
66
+
67
+ ### OUT
68
+ - Changes to Claude Code's native teammate protocol itself
69
+ - New messaging transport (still mailbox + native inbox)
70
+ - Multi-project per agent (one project at a time per directory entry)
71
+ - Modifying AGENTS.md content (directory is a pointer, not an editor)
72
+
73
+ ## Detailed Design
74
+
75
+ ### 1. New Module: `src/lib/agent-directory.ts`
76
+
77
+ Persistent JSON registry at `~/.genie/agent-directory.json`.
78
+
79
+ ```typescript
80
+ // Schema
81
+ interface DirectoryEntry {
82
+ name: string; // unique key, e.g., "totvs-pm"
83
+ home: string; // absolute path to agent home (contains AGENTS.md)
84
+ project: string; // absolute path to project repo (CWD at spawn)
85
+ team?: string; // optional default team grouping
86
+ registeredAt: string; // ISO timestamp
87
+ }
88
+
89
+ interface AgentDirectory {
90
+ entries: Record<string, DirectoryEntry>;
91
+ lastUpdated: string;
92
+ }
93
+
94
+ // Public API
95
+ register(name, home, project, team?): void // persist entry
96
+ unregister(name): void // remove entry
97
+ resolve(name): DirectoryEntry | null // lookup by name
98
+ list(): DirectoryEntry[] // all entries
99
+ loadIdentity(name): string | null // read AGENTS.md from home
100
+ ```
101
+
102
+ **Storage:** Same `~/.genie/` directory as `workers.json` and `config.json`. Uses the same file-lock pattern from `agent-registry.ts` for concurrent access safety.
103
+
104
+ **Path validation:** `resolve()` returns the entry as-is (fast). `loadIdentity()` checks if `home/AGENTS.md` exists and returns null if missing. Spawn command fails fast with clear error on missing paths.
105
+
106
+ ### 2. Modified: `src/lib/provider-adapters.ts`
107
+
108
+ Add `systemPrompt?: string` to `SpawnParams`:
109
+
110
+ ```typescript
111
+ export interface SpawnParams {
112
+ // ... existing fields ...
113
+ /** System prompt content to inject via --append-system-prompt. */
114
+ systemPrompt?: string;
115
+ }
116
+ ```
117
+
118
+ In `buildClaudeCommand()`: if `systemPrompt` is provided, persist to file via the existing `persistSystemPrompt()` pattern from `team-lead-command.ts`, then add `--append-system-prompt "$(cat <path>)"`.
119
+
120
+ **Implementation detail:** Extract `persistSystemPrompt()` from `team-lead-command.ts` into a shared utility (or just import it). The file goes to `~/.genie/prompts/<agent-name>.md`. The existing `promptMode` config (`'append'` vs `'system'`) is respected.
121
+
122
+ ### 3. Modified: `src/term-commands/agents.ts` — spawn command
123
+
124
+ Change the spawn command signature from:
125
+
126
+ ```
127
+ genie agent spawn --role <role> [--team <team>] [--cwd <path>] ...
128
+ ```
129
+
130
+ To:
131
+
132
+ ```
133
+ genie agent spawn [name] --role <role> [--team <team>] [--cwd <path>] ...
134
+ ```
135
+
136
+ Resolution logic in `handleWorkerSpawn()`:
137
+
138
+ ```
139
+ 1. If positional `name` provided:
140
+ a. Resolve from agent directory
141
+ b. If not found → error: "Agent '<name>' not registered. Run: genie agent register ..."
142
+ c. Set CWD = entry.project (override --cwd if not explicitly provided)
143
+ d. Load AGENTS.md from entry.home → set systemPrompt on SpawnParams
144
+ e. Set GENIE_AGENT_NAME = name (via env in launch command)
145
+ f. Use entry.team as default team (if --team not explicit)
146
+ g. Use name as the role for native team registration
147
+
148
+ 2. If no positional name (--role provided):
149
+ a. Existing behavior, unchanged
150
+ b. No directory lookup
151
+ ```
152
+
153
+ **Backward compat:** `--role` becomes optional (was `.requiredOption`). Validation: either positional `name` or `--role` must be provided, error otherwise.
154
+
155
+ ### 4. New Subcommands in `agents.ts`
156
+
157
+ ```
158
+ genie agent register <name> --home <path> --project <path> [--team <team>]
159
+ genie agent unregister <name>
160
+ genie agent directory [--json]
161
+ ```
162
+
163
+ **register:** Validates both paths exist on disk. Writes to `agent-directory.json`.
164
+
165
+ **unregister:** Removes entry. Does not affect running workers or templates.
166
+
167
+ **directory:** Lists all registered agents with runtime state enrichment:
168
+
169
+ ```
170
+ NAME HOME PROJECT STATUS TEAM
171
+ totvs-pm ~/.../totvs-pm ~/.../projects/totvs-poc idle recon
172
+ totvs-engineer ~/.../totvs-recon-engineer ~/.../projects/totvs-poc working recon
173
+ totvs-qa ~/.../totvs-qa ~/.../projects/totvs-poc stopped —
174
+ ```
175
+
176
+ STATUS is derived by cross-referencing the worker registry: if a worker with matching name/role exists and its pane is alive → show its state. Otherwise → "stopped".
177
+
178
+ ### 5. Modified: `src/lib/protocol-router.ts` — sendMessage()
179
+
180
+ Add directory-aware resolution as the **first** lookup tier in `sendMessage()`:
181
+
182
+ ```
183
+ Current: resolveRecipient(to) → workers by ID > role > team:role
184
+ New: directoryResolve(to) → agent directory by name
185
+ ↓ (if found + alive)
186
+ deliver directly
187
+ ↓ (if found + not alive)
188
+ auto-spawn from directory entry → deliver
189
+ ↓ (if not found in directory)
190
+ resolveRecipient(to) → existing worker registry resolution
191
+ ```
192
+
193
+ **Auto-spawn from directory:** When a directory agent isn't running, the router:
194
+ 1. Calls `agentDirectory.resolve(to)` → gets home + project
195
+ 2. Calls `agentDirectory.loadIdentity(to)` → gets AGENTS.md content
196
+ 3. Spawns using the same `spawnWorkerFromTemplate` pattern but with directory-derived params
197
+ 4. Waits for ready, delivers message
198
+
199
+ **Collision handling:** If an agent name in the directory matches a worker ID from a different context, directory wins. A debug-level warning is logged.
200
+
201
+ ### 6. Modified: `src/hooks/handlers/auto-spawn.ts`
202
+
203
+ The hook also needs directory awareness for the case where Claude Code's SendMessage fires before the protocol router handles it:
204
+
205
+ ```
206
+ Current: check worker registry → check templates → spawn from template
207
+ New: check worker registry → check agent directory → check templates
208
+ ```
209
+
210
+ If the directory has the recipient, spawn using directory identity (same as protocol-router path). This keeps the hook and router consistent.
211
+
212
+ ### 7. Identity Injection Flow (end-to-end)
213
+
214
+ ```
215
+ 1. Human runs: genie agent register totvs-pm \
216
+ --home /home/genie/agents/namastexlabs/totvs-pm \
217
+ --project /home/genie/agents/namastexlabs/projects/totvs-poc
218
+
219
+ 2. Human (or another agent) runs: genie agent spawn totvs-pm
220
+
221
+ 3. handleWorkerSpawn():
222
+ a. directory.resolve("totvs-pm") → { home: "/...totvs-pm", project: "/...totvs-poc" }
223
+ b. directory.loadIdentity("totvs-pm") → reads /...totvs-pm/AGENTS.md → string content
224
+ c. persistSystemPrompt("totvs-pm", content) → writes ~/.genie/prompts/totvs-pm.md
225
+ d. SpawnParams.systemPrompt = content
226
+ e. buildClaudeCommand() adds: --append-system-prompt "$(cat ~/.genie/prompts/totvs-pm.md)"
227
+ f. Launch env includes: GENIE_AGENT_NAME=totvs-pm
228
+ g. tmux pane CWD = /...totvs-poc
229
+
230
+ 4. Agent starts with:
231
+ - Its own AGENTS.md as system prompt (independent identity)
232
+ - CWD in the project repo (not its home directory)
233
+ - GENIE_AGENT_NAME set (identity-inject hook tags outgoing messages)
234
+
235
+ 5. PM sends to engineer: genie send 'assess filter extension' --to totvs-engineer
236
+ a. protocol-router.sendMessage() → directoryResolve("totvs-engineer")
237
+ b. If alive → deliver
238
+ c. If not alive → auto-spawn from directory → deliver
239
+ d. No --team flag needed
240
+ ```
241
+
242
+ ## Risks
243
+
244
+ | ID | Risk | Severity | Mitigation |
245
+ |----|------|----------|------------|
246
+ | R1 | **Dual resolution ambiguity** — directory name collides with worker ID/role from different team | Medium | Directory wins on exact name match. Log warning on collision. |
247
+ | R2 | **Stale directory entries** — agent home moved/deleted, spawn fails | Low | `loadIdentity()` returns null on missing AGENTS.md. Spawn fails fast with clear error. `genie agent directory` validates paths and shows warnings. |
248
+ | R3 | **`--append-system-prompt` size limits** — large AGENTS.md files | Low | Reuse `persistSystemPrompt()` file-persist + `$(cat)` pattern from `team-lead-command.ts`. Already battle-tested. |
249
+ | R4 | **Auto-spawn race** — hook and router both try to spawn | Medium | Both paths check `isPaneAlive()` before spawning. `cleanupDeadWorkers()` runs before spawn. Same guards that prevent double-spawn today. |
250
+ | R5 | **`--role` required → optional** — could break scripts | Low | Validation: require either positional `name` OR `--role`. Error message guides users. Existing `--role` invocations are unaffected. |
251
+
252
+ ## Acceptance Criteria
253
+
254
+ 1. **Register + resolve:** `genie agent register totvs-pm --home /path --project /path` persists to `~/.genie/agent-directory.json`. `genie agent directory` lists it.
255
+ 2. **Spawn by name:** `genie agent spawn totvs-pm` sets CWD to project, injects AGENTS.md from home via `--append-system-prompt`, sets `GENIE_AGENT_NAME=totvs-pm`.
256
+ 3. **Independent identity:** Two directory agents spawned into the same project have different AGENTS.md injected. Verified by differing `~/.genie/prompts/<name>.md`.
257
+ 4. **Flat messaging:** `genie send 'hello' --to totvs-engineer` delivers without `--team`, resolving via directory.
258
+ 5. **Auto-spawn + deliver:** Sending to an offline directory agent triggers spawn then delivery.
259
+ 6. **Template auto-creation:** Spawning a directory agent saves a `WorkerTemplate` for crash recovery.
260
+ 7. **Backward compat:** `genie agent spawn --role implementor --team myteam` works unchanged.
261
+ 8. **Path validation:** Spawn fails fast with clear error if home or project path doesn't exist.
262
+ 9. **Unregister:** `genie agent unregister totvs-pm` removes from directory without affecting running workers.
263
+
264
+ ## Implementation Groups
265
+
266
+ ### Group 1: Foundation (no behavioral changes)
267
+ - [ ] Create `src/lib/agent-directory.ts` with register/unregister/resolve/list/loadIdentity
268
+ - [ ] Extract `persistSystemPrompt()` from `team-lead-command.ts` into shared util
269
+ - [ ] Add `systemPrompt?: string` to `SpawnParams` in `provider-adapters.ts`
270
+ - [ ] Wire `systemPrompt` into `buildClaudeCommand()` using persist+cat pattern
271
+
272
+ ### Group 2: Spawn Integration
273
+ - [ ] Add `register`, `unregister`, `directory` subcommands to `agents.ts`
274
+ - [ ] Add optional `[name]` positional to `spawn` command
275
+ - [ ] Make `--role` conditionally required (required if no positional name)
276
+ - [ ] Wire directory resolution into `handleWorkerSpawn()`
277
+ - [ ] Set `GENIE_AGENT_NAME` and CWD from directory entry at spawn
278
+
279
+ ### Group 3: Messaging Integration
280
+ - [ ] Add directory-aware first-pass resolution in `protocol-router.ts:sendMessage()`
281
+ - [ ] Add directory lookup in `auto-spawn.ts` hook (before template fallback)
282
+ - [ ] Implement auto-spawn-from-directory in protocol router for offline agents
283
+ - [ ] Verify `identity-inject.ts` works with directory-spawned agents (uses GENIE_AGENT_NAME — should work as-is)
284
+
285
+ ### Group 4: Polish + Validation
286
+ - [ ] `genie agent directory` shows runtime state by cross-referencing worker registry
287
+ - [ ] Path validation warnings in directory listing
288
+ - [ ] Tests for agent-directory.ts (register, resolve, loadIdentity)
289
+ - [ ] Tests for directory-aware spawn (mock directory, verify systemPrompt injection)
290
+ - [ ] Integration test: register → spawn → send message → verify delivery
291
+
292
+ ## Files Changed
293
+
294
+ | File | Change Type | Description |
295
+ |------|------------|-------------|
296
+ | `src/lib/agent-directory.ts` | **New** | Persistent agent directory module |
297
+ | `src/lib/provider-adapters.ts` | Modified | Add `systemPrompt` to SpawnParams, wire into buildClaudeCommand |
298
+ | `src/lib/team-lead-command.ts` | Modified | Extract `persistSystemPrompt` to shared location |
299
+ | `src/term-commands/agents.ts` | Modified | Add register/unregister/directory subcommands, optional positional spawn |
300
+ | `src/lib/protocol-router.ts` | Modified | Directory-first resolution in sendMessage |
301
+ | `src/hooks/handlers/auto-spawn.ts` | Modified | Directory lookup before template fallback |
302
+ | `src/types/genie-config.ts` | Unchanged | No config schema changes needed |
303
+
304
+ ## Non-Goals (Explicit)
305
+
306
+ - No changes to Claude Code's native teammate protocol
307
+ - No new messaging transport
308
+ - No multi-project support per agent
309
+ - No auto-discovery of agent directories (explicit registration only)
310
+ - No modifications to AGENTS.md content from genie