legion-cc 0.20.1 → 0.21.0
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.
- package/agents/architect.md +1 -0
- package/agents/code-analyst.md +1 -0
- package/agents/context-curator.md +1 -0
- package/agents/implementer.md +1 -0
- package/agents/legion-orchestrator.md +20 -20
- package/agents/memory.md +3 -2
- package/agents/planner.md +1 -0
- package/bin/install.js +24 -16
- package/commands/legion/auto.md +2 -2
- package/commands/legion/codebase.md +1 -1
- package/commands/legion/cycle.md +1 -1
- package/commands/legion/quick.md +1 -1
- package/hooks/legion-context-monitor.js +7 -0
- package/hooks/legion-mcp-advisor.js +26 -21
- package/package.json +2 -2
package/agents/architect.md
CHANGED
|
@@ -97,6 +97,7 @@ When your work is complete, execute these steps IN ORDER:
|
|
|
97
97
|
|
|
98
98
|
1. **Write report to task**: `TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your full structured report>")`
|
|
99
99
|
2. **Notify teammates** (if needed): `SendMessage(type: "message", recipient: "<teammate-name>", content: "<report or summary>", summary: "<brief>")`
|
|
100
|
+
3. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after steps 1-2.
|
|
100
101
|
|
|
101
102
|
Your task ID and team name are provided in your spawn prompt. If not provided, check `TaskList` to find your assigned task.
|
|
102
103
|
|
package/agents/code-analyst.md
CHANGED
|
@@ -92,6 +92,7 @@ When your work is complete, execute these steps IN ORDER:
|
|
|
92
92
|
|
|
93
93
|
1. **Write report to task**: `TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your full structured report>")`
|
|
94
94
|
2. **Notify teammates** (if needed): `SendMessage(type: "message", recipient: "<teammate-name>", content: "<report or summary>", summary: "<brief>")`
|
|
95
|
+
3. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after steps 1-2.
|
|
95
96
|
|
|
96
97
|
Your task ID and team name are provided in your spawn prompt. If not provided, check `TaskList` to find your assigned task.
|
|
97
98
|
|
|
@@ -99,6 +99,7 @@ When your work is complete, execute these steps IN ORDER:
|
|
|
99
99
|
|
|
100
100
|
1. **Write report to task**: `TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your full context document>")`
|
|
101
101
|
2. **Notify teammates** (if needed): In quick pipeline, send Bundle Section 3 to architect via `SendMessage`. In cycle pipeline, TaskUpdate is sufficient.
|
|
102
|
+
3. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after steps 1-2.
|
|
102
103
|
|
|
103
104
|
Your task ID and team name are provided in your spawn prompt. If not provided, check `TaskList` to find your assigned task.
|
|
104
105
|
|
package/agents/implementer.md
CHANGED
|
@@ -113,6 +113,7 @@ When your work is complete, execute these steps IN ORDER:
|
|
|
113
113
|
|
|
114
114
|
1. **Write report to task**: `TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your full implementation report>")`
|
|
115
115
|
2. **Notify teammates** (if needed): `SendMessage(type: "message", recipient: "<teammate-name>", content: "<summary>", summary: "<brief>")`
|
|
116
|
+
3. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after steps 1-2.
|
|
116
117
|
|
|
117
118
|
Your task ID and team name are provided in your spawn prompt. If not provided, check `TaskList` to find your assigned task.
|
|
118
119
|
|
|
@@ -122,10 +122,10 @@ Cap at 10.
|
|
|
122
122
|
3. Spawn 2 teammates **in parallel** — include task IDs in prompts:
|
|
123
123
|
```
|
|
124
124
|
Agent(team_name: ..., name: "context-curator", subagent_type: "context-curator",
|
|
125
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-1-id>\n\nCollect project context. Write Bundle Section 3 following the ## Bundle Section 3: Project Context schema (Identity, Rules & Conventions, Build/Run/Test, Code Style, Config & Environment, Key Constraints). CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\n1. TaskUpdate(taskId: '<task-1-id>', status: 'completed', description: '<Bundle Section 3>')\n2. SendMessage(type: 'message', recipient: 'architect', content: '<Bundle Section 3>', summary: 'Bundle Section 3 ready')\nBoth steps REQUIRED.")
|
|
125
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-1-id>\n\nCollect project context. Write Bundle Section 3 following the ## Bundle Section 3: Project Context schema (Identity, Rules & Conventions, Build/Run/Test, Code Style, Config & Environment, Key Constraints). CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\n1. TaskUpdate(taskId: '<task-1-id>', status: 'completed', description: '<Bundle Section 3>')\n2. SendMessage(type: 'message', recipient: 'architect', content: '<Bundle Section 3>', summary: 'Bundle Section 3 ready')\nBoth steps REQUIRED.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
126
126
|
|
|
127
127
|
Agent(team_name: ..., name: "architect", subagent_type: "architect",
|
|
128
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-2-id>\n\nWait for Bundle Section 3 from context-curator via SendMessage. Then write Bundle Sections 1+2 combined (Architecture + Code Analysis, budget: 300-600 lines) following the schemas:\n- ## Bundle Sections 1+2: Architecture + Code Analysis\n- Subsections: 1.1 Approach, 1.2 Change Boundaries, 1.3 Architecture Decisions, 2.1 Entry Points, 2.2 Files to Change, 2.3 Risks\n\nAND produce a lightweight Execution Pack (Plan + Diff + Acceptance Criteria + Rollback). Write both as your task output via TaskUpdate.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-2-id>', status: 'completed', description: '<Bundle Sections 1+2 + Execution Pack>')\nDo NOT go idle without calling TaskUpdate.")
|
|
128
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-2-id>\n\nWait for Bundle Section 3 from context-curator via SendMessage. Then write Bundle Sections 1+2 combined (Architecture + Code Analysis, budget: 300-600 lines) following the schemas:\n- ## Bundle Sections 1+2: Architecture + Code Analysis\n- Subsections: 1.1 Approach, 1.2 Change Boundaries, 1.3 Architecture Decisions, 2.1 Entry Points, 2.2 Files to Change, 2.3 Risks\n\nAND produce a lightweight Execution Pack (Plan + Diff + Acceptance Criteria + Rollback). Write both as your task output via TaskUpdate.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-2-id>', status: 'completed', description: '<Bundle Sections 1+2 + Execution Pack>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
129
129
|
```
|
|
130
130
|
4. Context Curator collects context → writes Bundle Section 3 to task via TaskUpdate → sends to Architect via SendMessage
|
|
131
131
|
5. Architect receives Bundle Section 3 → writes Bundle Sections 1+2 + Execution Pack to task via TaskUpdate
|
|
@@ -134,9 +134,9 @@ Cap at 10.
|
|
|
134
134
|
8. Spawn Implementer with full Execution Pack text from TaskGet(task-2-id) and task 3's ID:
|
|
135
135
|
```
|
|
136
136
|
Agent(team_name: ..., name: "implementer", subagent_type: "implementer",
|
|
137
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-3-id>\n\n<full text from TaskGet(task-2-id).description>\n\nThe above contains Bundle Sections 1+2 and an Execution Pack. Execute the Plan from the Execution Pack. Use Bundle sections for architectural context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-3-id>', status: 'completed', description: '<implementation report>')\nDo NOT go idle without calling TaskUpdate.")
|
|
137
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-3-id>\n\n<full text from TaskGet(task-2-id).description>\n\nThe above contains Bundle Sections 1+2 and an Execution Pack. Execute the Plan from the Execution Pack. Use Bundle sections for architectural context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-3-id>', status: 'completed', description: '<implementation report>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
138
138
|
```
|
|
139
|
-
9. Poll TaskList until task 3 completed → Read result from TaskGet(task-3-id) →
|
|
139
|
+
9. Poll TaskList until task 3 completed → Read result from TaskGet(task-3-id) → Call `TeamDelete`. Optionally send `shutdown_request` as best-effort, but do NOT wait for `shutdown_response`.
|
|
140
140
|
|
|
141
141
|
## Cycle Pipeline (score 7-10)
|
|
142
142
|
|
|
@@ -154,13 +154,13 @@ Cap at 10.
|
|
|
154
154
|
3. Spawn 3 teammates **in parallel** — each prompt MUST include task, team name, task ID, and Bundle Section instruction:
|
|
155
155
|
```
|
|
156
156
|
Agent(team_name: ..., name: "architect", subagent_type: "architect",
|
|
157
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-1-id>\n\nAnalyze architecture for this task. Write Bundle Section 1 following the ## Bundle Section 1: Architecture schema. CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-1-id>', status: 'completed', description: '<Bundle Section 1>')\nDo NOT go idle without calling TaskUpdate.")
|
|
157
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-1-id>\n\nAnalyze architecture for this task. Write Bundle Section 1 following the ## Bundle Section 1: Architecture schema. CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-1-id>', status: 'completed', description: '<Bundle Section 1>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
158
158
|
|
|
159
159
|
Agent(team_name: ..., name: "code-analyst", subagent_type: "code-analyst",
|
|
160
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-2-id>\n\nAnalyze codebase for this task. Write Bundle Section 2 following the ## Bundle Section 2: Code Analysis schema. CRITICAL: MUST NOT exceed 600 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-2-id>', status: 'completed', description: '<Bundle Section 2>')\nDo NOT go idle without calling TaskUpdate.")
|
|
160
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-2-id>\n\nAnalyze codebase for this task. Write Bundle Section 2 following the ## Bundle Section 2: Code Analysis schema. CRITICAL: MUST NOT exceed 600 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-2-id>', status: 'completed', description: '<Bundle Section 2>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
161
161
|
|
|
162
162
|
Agent(team_name: ..., name: "context-curator", subagent_type: "context-curator",
|
|
163
|
-
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-3-id>\n\nCollect project context. Write Bundle Section 3 following the ## Bundle Section 3: Project Context schema. CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-3-id>', status: 'completed', description: '<Bundle Section 3>')\nDo NOT go idle without calling TaskUpdate.")
|
|
163
|
+
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-3-id>\n\nCollect project context. Write Bundle Section 3 following the ## Bundle Section 3: Project Context schema. CRITICAL: MUST NOT exceed 400 lines.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-3-id>', status: 'completed', description: '<Bundle Section 3>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
164
164
|
```
|
|
165
165
|
4. Wait for all 3 to complete — poll `TaskList` until tasks 1, 2, 3 are all `status: "completed"`
|
|
166
166
|
|
|
@@ -170,12 +170,12 @@ Cap at 10.
|
|
|
170
170
|
Spawn Planner:
|
|
171
171
|
```
|
|
172
172
|
Agent(team_name: ..., name: "planner", subagent_type: "planner",
|
|
173
|
-
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-4-id>\n\n## Task\n<the user's original request>\n\n## Phase 1 Bundle Section Task IDs\nRead each Bundle Section using TaskGet(taskId) — the section is in the task's `description` field. Each section starts with `## Bundle Section N:`.\n- **Architect (Bundle Section 1)**: TaskGet('<task-1-id>')\n- **Code Analyst (Bundle Section 2)**: TaskGet('<task-2-id>')\n- **Context Curator (Bundle Section 3)**: TaskGet('<task-3-id>')\n\nRead all three Bundle Sections, assemble the Bundle, then produce an Execution Pack with sub-tasks, pseudo-diffs, acceptance criteria, risks, and rollback. Use ToolSearch('+legion-sequential-thinking') and ToolSearch('+legion-memory') before plan construction. Read Infrastructure Notes sections (§1.6, §2.7) from Bundle Sections. Query mcp__legion-memory__read_graph for cross-session context. If legion-memory MCP is unavailable, proceed without. Include User Questions section (≤3) only if critical clarifications are needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-4-id>', status: 'completed', description: '<your full Execution Pack>')\nIf you have user questions, also: SendMessage(type: 'message', recipient: 'legion-orchestrator', content: '<questions>', summary: 'Clarifying questions for user')\nDo NOT go idle without calling TaskUpdate.")
|
|
173
|
+
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-4-id>\n\n## Task\n<the user's original request>\n\n## Phase 1 Bundle Section Task IDs\nRead each Bundle Section using TaskGet(taskId) — the section is in the task's `description` field. Each section starts with `## Bundle Section N:`.\n- **Architect (Bundle Section 1)**: TaskGet('<task-1-id>')\n- **Code Analyst (Bundle Section 2)**: TaskGet('<task-2-id>')\n- **Context Curator (Bundle Section 3)**: TaskGet('<task-3-id>')\n\nRead all three Bundle Sections, assemble the Bundle, then produce an Execution Pack with sub-tasks, pseudo-diffs, acceptance criteria, risks, and rollback. Use ToolSearch('+legion-sequential-thinking') and ToolSearch('+legion-memory') before plan construction. Read Infrastructure Notes sections (§1.6, §2.7) from Bundle Sections. Query mcp__legion-memory__read_graph for cross-session context. If legion-memory MCP is unavailable, proceed without. Include User Questions section (≤3) only if critical clarifications are needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-4-id>', status: 'completed', description: '<your full Execution Pack>')\nIf you have user questions, also: SendMessage(type: 'message', recipient: 'legion-orchestrator', content: '<questions>', summary: 'Clarifying questions for user')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
174
174
|
```
|
|
175
175
|
Spawn Memory (fire-and-forget):
|
|
176
176
|
```
|
|
177
|
-
Agent(team_name: ..., name: "memory", subagent_type: "general-purpose",
|
|
178
|
-
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-6-id>\n\n## Phase 1 Bundle Section Task IDs\nRead Bundle Sections 1 and 2 using TaskGet(taskId) — the section is in the task's `description` field.\n- **Architect (Bundle Section 1)**: TaskGet('<task-1-id>')\n- **Code Analyst (Bundle Section 2)**: TaskGet('<task-2-id>')\n\nLoad MCP tools first: ToolSearch(\"+legion-memory\"). Then extract key findings and store them in project memory via MCP legion-memory server. Pay special attention to Infrastructure Notes (§1.6, §2.7) — store these as separate named entities using mcp__legion-memory__create_entities and mcp__legion-memory__add_observations. If MCP is unavailable, note the error and complete anyway.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-6-id>', status: 'completed', description: '<summary of stored memories>')\nDo NOT go idle without calling TaskUpdate.")
|
|
177
|
+
Agent(team_name: ..., name: "memory", subagent_type: "general-purpose", model: "haiku",
|
|
178
|
+
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-6-id>\n\n## Phase 1 Bundle Section Task IDs\nRead Bundle Sections 1 and 2 using TaskGet(taskId) — the section is in the task's `description` field.\n- **Architect (Bundle Section 1)**: TaskGet('<task-1-id>')\n- **Code Analyst (Bundle Section 2)**: TaskGet('<task-2-id>')\n\nLoad MCP tools first: ToolSearch(\"+legion-memory\"). Then extract key findings and store them in project memory via MCP legion-memory server. Pay special attention to Infrastructure Notes (§1.6, §2.7) — store these as separate named entities using mcp__legion-memory__create_entities and mcp__legion-memory__add_observations. If MCP is unavailable, note the error and complete anyway.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-6-id>', status: 'completed', description: '<summary of stored memories>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
179
179
|
```
|
|
180
180
|
6. Wait for plan — poll `TaskList` until tasks 4 and 6 are `status: "completed"`
|
|
181
181
|
|
|
@@ -195,10 +195,10 @@ Cap at 10.
|
|
|
195
195
|
9. Spawn Implementer with full Execution Pack text from TaskGet(task-4-id) and task 5's ID:
|
|
196
196
|
```
|
|
197
197
|
Agent(team_name: ..., name: "implementer", subagent_type: "implementer",
|
|
198
|
-
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-5-id>\n\n<full text from TaskGet(task-4-id).description>\n\nThe Execution Pack above contains Plan, Diff, Acceptance Criteria, Risks, and Rollback.\nExecute the Plan. Use Bundle References (TaskGet) for deeper context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-5-id>', status: 'completed', description: '<your implementation report>')\nDo NOT go idle without calling TaskUpdate.")
|
|
198
|
+
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-5-id>\n\n<full text from TaskGet(task-4-id).description>\n\nThe Execution Pack above contains Plan, Diff, Acceptance Criteria, Risks, and Rollback.\nExecute the Plan. Use Bundle References (TaskGet) for deeper context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-5-id>', status: 'completed', description: '<your implementation report>')\nDo NOT go idle without calling TaskUpdate.\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
199
199
|
```
|
|
200
200
|
10. Wait for implementation — poll `TaskList` until task 5 is `status: "completed"`
|
|
201
|
-
11. Read final report from `TaskGet(task-5-id).description` →
|
|
201
|
+
11. Read final report from `TaskGet(task-5-id).description` → Call `TeamDelete`. Optionally send `shutdown_request` as best-effort, but do NOT wait for `shutdown_response`.
|
|
202
202
|
|
|
203
203
|
## Partial Pipeline (score 4-6)
|
|
204
204
|
|
|
@@ -262,7 +262,7 @@ Agent(
|
|
|
262
262
|
3. **Create team before spawning** — TeamCreate must come before Agent calls
|
|
263
263
|
4. **Pass task IDs** — give Planner the Phase 1 task IDs to read reports directly
|
|
264
264
|
5. **Monitor progress** — check TaskList between phases
|
|
265
|
-
6. **Clean shutdown** —
|
|
265
|
+
6. **Clean shutdown** — Call `TeamDelete` immediately. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
266
266
|
7. **Report to user** — summarize what was done after pipeline completes
|
|
267
267
|
|
|
268
268
|
### Agent Tool Reference
|
|
@@ -290,7 +290,7 @@ Spawn subagents using the **Agent** tool:
|
|
|
290
290
|
**Example:**
|
|
291
291
|
```json
|
|
292
292
|
{
|
|
293
|
-
"prompt": "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-id>\n\nAnalyze architecture, approach, boundaries, prior art.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-id>', status: 'completed', description: '<your full report>')",
|
|
293
|
+
"prompt": "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-id>\n\nAnalyze architecture, approach, boundaries, prior art.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-id>', status: 'completed', description: '<your full report>')\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).",
|
|
294
294
|
"description": "Architectural analysis",
|
|
295
295
|
"subagent_type": "architect",
|
|
296
296
|
"model": "opus"
|
|
@@ -356,7 +356,7 @@ executionPack = TaskGet(Task2.id).description
|
|
|
356
356
|
|
|
357
357
|
// Phase 5: Spawn Implementer with full Execution Pack
|
|
358
358
|
Agent(name: "implementer", subagent_type: "implementer",
|
|
359
|
-
prompt: "## Assignment\n**Your task ID**: " + Task3.id + "\n\n" + executionPack + "\n\nExecute the Plan from the Execution Pack. Use Bundle sections for context.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + Task3.id + "', ...)")
|
|
359
|
+
prompt: "## Assignment\n**Your task ID**: " + Task3.id + "\n\n" + executionPack + "\n\nExecute the Plan from the Execution Pack. Use Bundle sections for context.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + Task3.id + "', ...)\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
360
360
|
|
|
361
361
|
// Phase 6: Poll until task 3 completed, read final report
|
|
362
362
|
result = TaskGet(Task3.id).description
|
|
@@ -384,10 +384,10 @@ Agent(..., name: "context-curator", subagent_type: "context-curator",
|
|
|
384
384
|
while not all [t1, t2, t3] completed: check TaskList()
|
|
385
385
|
|
|
386
386
|
// Spawn Planner AND Memory in parallel (Phase 2)
|
|
387
|
-
Agent(..., name: "planner", prompt: "## Assignment\n**Your task ID**: " + t4.id + "\n\n## Task\n<the user's original request>\n\n## Phase 1 Bundle Section Task IDs\nRead each Bundle Section using TaskGet(taskId). Each starts with ## Bundle Section N:.\n- Architect (§1): TaskGet('" + t1.id + "')\n- Code Analyst (§2): TaskGet('" + t2.id + "')\n- Context Curator (§3): TaskGet('" + t3.id + "')\n\nAssemble Bundle, produce Execution Pack with optional user questions (≤3).\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t4.id + "', ...)")
|
|
387
|
+
Agent(..., name: "planner", prompt: "## Assignment\n**Your task ID**: " + t4.id + "\n\n## Task\n<the user's original request>\n\n## Phase 1 Bundle Section Task IDs\nRead each Bundle Section using TaskGet(taskId). Each starts with ## Bundle Section N:.\n- Architect (§1): TaskGet('" + t1.id + "')\n- Code Analyst (§2): TaskGet('" + t2.id + "')\n- Context Curator (§3): TaskGet('" + t3.id + "')\n\nAssemble Bundle, produce Execution Pack with optional user questions (≤3).\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t4.id + "', ...)\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
388
388
|
|
|
389
|
-
Agent(..., name: "memory", subagent_type: "general-purpose",
|
|
390
|
-
prompt: "## Assignment\n**Your task ID**: " + t6.id + "\n\n## Phase 1 Bundle Section Task IDs\n- Architect (§1): TaskGet('" + t1.id + "')\n- Code Analyst (§2): TaskGet('" + t2.id + "')\n\nExtract key findings and store in project memory via MCP legion-memory server.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t6.id + "', ...)")
|
|
389
|
+
Agent(..., name: "memory", subagent_type: "general-purpose", model: "haiku",
|
|
390
|
+
prompt: "## Assignment\n**Your task ID**: " + t6.id + "\n\n## Phase 1 Bundle Section Task IDs\n- Architect (§1): TaskGet('" + t1.id + "')\n- Code Analyst (§2): TaskGet('" + t2.id + "')\n\nExtract key findings and store in project memory via MCP legion-memory server.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t6.id + "', ...)\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
391
391
|
|
|
392
392
|
// Phase 2.5: Check for Planner questions → AskUserQuestion if present
|
|
393
393
|
|
|
@@ -396,7 +396,7 @@ executionPack = TaskGet(t4.id).description
|
|
|
396
396
|
// Extract ## Plan section, present via AskUserQuestion
|
|
397
397
|
|
|
398
398
|
// Spawn Implementer with full Execution Pack
|
|
399
|
-
Agent(..., name: "implementer", prompt: "## Assignment\n**Your task ID**: " + t5.id + "\n\n" + executionPack + "\n\nExecute the Plan. Use Bundle References (TaskGet) for deeper context if needed.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t5.id + "', ...)")
|
|
399
|
+
Agent(..., name: "implementer", prompt: "## Assignment\n**Your task ID**: " + t5.id + "\n\n" + executionPack + "\n\nExecute the Plan. Use Bundle References (TaskGet) for deeper context if needed.\n\n## End of Work Protocol\nTaskUpdate(taskId: '" + t5.id + "', ...)\nIf you receive a shutdown_request message, respond: SendMessage(type: 'shutdown_response', request_id: '<requestId>', approve: true).")
|
|
400
400
|
```
|
|
401
401
|
|
|
402
402
|
## Behavioral Guidelines
|
|
@@ -426,5 +426,5 @@ Agent(..., name: "implementer", prompt: "## Assignment\n**Your task ID**: " + t5
|
|
|
426
426
|
4. **Read reports via TaskGet** — after a task is completed, call `TaskGet(taskId)` to read the report from the `description` field
|
|
427
427
|
5. **Pass task IDs to Planner** — give Planner the Phase 1 task IDs so it can read reports directly via TaskGet
|
|
428
428
|
6. **Create new tasks for each phase** — don't reuse tasks; Phase 2 is a new task (Planner), Phase 3 is another new task (Implementer)
|
|
429
|
-
7. **Shutdown gracefully** — after pipeline completes
|
|
429
|
+
7. **Shutdown gracefully** — Call `TeamDelete` immediately after pipeline completes. Optionally send `shutdown_request` as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
430
430
|
8. **Don't rely on stdout or SendMessage for reports** — reports are delivered via TaskUpdate(description). TaskGet reads them.
|
package/agents/memory.md
CHANGED
|
@@ -80,8 +80,9 @@ If MCP servers are available in the project, you MUST:
|
|
|
80
80
|
|
|
81
81
|
## End of Work Protocol (MANDATORY)
|
|
82
82
|
|
|
83
|
-
TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<summary of what was stored in memory, or error if MCP unavailable>")
|
|
84
|
-
Do NOT go idle without calling TaskUpdate.
|
|
83
|
+
1. TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<summary of what was stored in memory, or error if MCP unavailable>")
|
|
84
|
+
2. Do NOT go idle without calling TaskUpdate.
|
|
85
|
+
3. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after step 1.
|
|
85
86
|
|
|
86
87
|
## Rules
|
|
87
88
|
|
package/agents/planner.md
CHANGED
|
@@ -114,6 +114,7 @@ When your work is complete, execute these steps IN ORDER:
|
|
|
114
114
|
1. **Write Execution Pack to task**: `TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your full Execution Pack>")`
|
|
115
115
|
2. **Send questions to orchestrator** (if any): If your Execution Pack contains a `## User Questions` section with 1+ questions, also: `SendMessage(type: "message", recipient: "legion-orchestrator", content: "<questions text>", summary: "Clarifying questions for user")`
|
|
116
116
|
3. **Notify teammates** (if needed): `SendMessage(type: "message", recipient: "<teammate-name>", content: "<summary>", summary: "<brief>")`
|
|
117
|
+
4. **Respond to shutdown** (if received): If a `shutdown_request` message arrives, call `SendMessage(type: "shutdown_response", request_id: "<requestId>", approve: true)`. Do NOT wait actively for it — you may stop after steps 1-3.
|
|
117
118
|
|
|
118
119
|
Your task ID and team name are provided in your spawn prompt. If not provided, check `TaskList` to find your assigned task.
|
|
119
120
|
|
package/bin/install.js
CHANGED
|
@@ -88,13 +88,21 @@ const COMMAND_FILES = [
|
|
|
88
88
|
'update.md',
|
|
89
89
|
];
|
|
90
90
|
|
|
91
|
+
// Cross-platform helpers
|
|
92
|
+
const isWindows = process.platform === 'win32';
|
|
93
|
+
function npmCmd(cmd) { return isWindows ? cmd + '.cmd' : cmd; }
|
|
94
|
+
function makeHookCmd(hookPath) {
|
|
95
|
+
const p = isWindows ? hookPath.replace(/\\/g, '/') : hookPath;
|
|
96
|
+
return `node "${p}"`;
|
|
97
|
+
}
|
|
98
|
+
|
|
91
99
|
// Claude Code >=2.1 hook format: { matcher: {}, hooks: [{ type, command }] }
|
|
92
100
|
// Statusline is a top-level `statusLine` setting, not a hook event.
|
|
93
|
-
const STATUSLINE_CMD =
|
|
94
|
-
const CONTEXT_MONITOR_CMD =
|
|
95
|
-
const TEAMMATE_IDLE_CMD =
|
|
96
|
-
const TASK_COMPLETED_CMD =
|
|
97
|
-
const MCP_ADVISOR_CMD =
|
|
101
|
+
const STATUSLINE_CMD = makeHookCmd(path.join(hooksTarget, 'legion-statusline.js'));
|
|
102
|
+
const CONTEXT_MONITOR_CMD = makeHookCmd(path.join(hooksTarget, 'legion-context-monitor.js'));
|
|
103
|
+
const TEAMMATE_IDLE_CMD = makeHookCmd(path.join(hooksTarget, 'legion-teammate-idle.js'));
|
|
104
|
+
const TASK_COMPLETED_CMD = makeHookCmd(path.join(hooksTarget, 'legion-task-completed.js'));
|
|
105
|
+
const MCP_ADVISOR_CMD = makeHookCmd(path.join(hooksTarget, 'legion-mcp-advisor.js'));
|
|
98
106
|
|
|
99
107
|
// Marker prefix for identifying Legion hook entries in settings.json.
|
|
100
108
|
// All Legion hook commands start with this path prefix.
|
|
@@ -105,14 +113,14 @@ const LEGION_MCP_PREFIX = 'legion-';
|
|
|
105
113
|
|
|
106
114
|
const LEGION_MCP_SERVERS = {
|
|
107
115
|
'legion-memory': {
|
|
108
|
-
command: 'npx',
|
|
116
|
+
command: npmCmd('npx'),
|
|
109
117
|
args: ['-y', '@modelcontextprotocol/server-memory'],
|
|
110
118
|
env: {
|
|
111
119
|
MEMORY_FILE_PATH: path.join(os.homedir(), '.legion', 'memory.jsonl'),
|
|
112
120
|
},
|
|
113
121
|
},
|
|
114
122
|
'legion-sequential-thinking': {
|
|
115
|
-
command: 'npx',
|
|
123
|
+
command: npmCmd('npx'),
|
|
116
124
|
args: ['-y', '@modelcontextprotocol/server-sequential-thinking'],
|
|
117
125
|
},
|
|
118
126
|
};
|
|
@@ -169,7 +177,7 @@ function copyFile(src, dest, options) {
|
|
|
169
177
|
const tmpPath = dest + '.tmp.' + process.pid;
|
|
170
178
|
try {
|
|
171
179
|
fs.copyFileSync(src, tmpPath);
|
|
172
|
-
fs.chmodSync(tmpPath, mode);
|
|
180
|
+
if (!isWindows) fs.chmodSync(tmpPath, mode);
|
|
173
181
|
fs.renameSync(tmpPath, dest);
|
|
174
182
|
log(`copied ${path.basename(dest)}`);
|
|
175
183
|
} catch (err) {
|
|
@@ -387,13 +395,15 @@ function upsertHookEntry(settings, eventName, entry) {
|
|
|
387
395
|
settings.hooks[eventName] = [];
|
|
388
396
|
}
|
|
389
397
|
|
|
390
|
-
const existingIdx = settings.hooks[eventName].findIndex((e) =>
|
|
391
|
-
e.hooks && e.hooks.some((h) => h.command && h.command.includes(LEGION_HOOK_MARKER))
|
|
392
|
-
);
|
|
393
|
-
|
|
394
398
|
// Extract hook filename from command (e.g. 'node "/path/to/legion-foo.js"' → 'legion-foo.js')
|
|
395
399
|
const hookFile = path.basename(entry.hooks[0].command.replace(/"/g, ''));
|
|
396
400
|
|
|
401
|
+
const existingIdx = settings.hooks[eventName].findIndex((e) =>
|
|
402
|
+
e.hooks && e.hooks.some((h) => h.command &&
|
|
403
|
+
h.command.includes(LEGION_HOOK_MARKER) &&
|
|
404
|
+
path.basename(h.command.replace(/"/g, '')) === hookFile)
|
|
405
|
+
);
|
|
406
|
+
|
|
397
407
|
if (existingIdx === -1) {
|
|
398
408
|
settings.hooks[eventName].push(entry);
|
|
399
409
|
log(`registered hook: ${eventName} → ${hookFile}`);
|
|
@@ -472,15 +482,13 @@ function registerHooks() {
|
|
|
472
482
|
log('updated hook: PostToolUse → legion-context-monitor.js');
|
|
473
483
|
}
|
|
474
484
|
|
|
475
|
-
// ── TeammateIdle hook
|
|
485
|
+
// ── TeammateIdle hook (no matcher support — fires on every occurrence) ──
|
|
476
486
|
upsertHookEntry(settings, 'TeammateIdle', {
|
|
477
|
-
matcher: '*',
|
|
478
487
|
hooks: [{ type: 'command', command: TEAMMATE_IDLE_CMD }],
|
|
479
488
|
});
|
|
480
489
|
|
|
481
|
-
// ── TaskCompleted hook
|
|
490
|
+
// ── TaskCompleted hook (no matcher support — fires on every occurrence) ─
|
|
482
491
|
upsertHookEntry(settings, 'TaskCompleted', {
|
|
483
|
-
matcher: '*',
|
|
484
492
|
hooks: [{ type: 'command', command: TASK_COMPLETED_CMD }],
|
|
485
493
|
});
|
|
486
494
|
|
package/commands/legion/auto.md
CHANGED
|
@@ -78,7 +78,7 @@ Announce your score and selected pipeline to the user before proceeding.
|
|
|
78
78
|
Agent(team_name: ..., name: "implementer", subagent_type: "implementer",
|
|
79
79
|
prompt: "## Assignment\n**Task**: <task>\n**Team**: <team-name>\n**Your task ID**: <task-3-id>\n\n<full text from TaskGet(task-2-id).description>\n\nThe above contains Bundle Sections 1+2 and an Execution Pack. Execute the Plan from the Execution Pack. Use Bundle sections for architectural context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-3-id>', status: 'completed', description: '<implementation report>')\nDo NOT go idle without calling TaskUpdate.")
|
|
80
80
|
```
|
|
81
|
-
9. Poll TaskList until task 3 completed → Read result from TaskGet(task-3-id) →
|
|
81
|
+
9. Poll TaskList until task 3 completed → Read result from TaskGet(task-3-id) → Call `TeamDelete`. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
82
82
|
|
|
83
83
|
---
|
|
84
84
|
|
|
@@ -153,7 +153,7 @@ Escalation: shutdown quick team → create cycle team → run full Cycle Pipelin
|
|
|
153
153
|
prompt: "## Assignment\n**Team**: <team-name>\n**Your task ID**: <task-5-id>\n\n<full text from TaskGet(task-4-id).description>\n\nThe Execution Pack above contains Plan, Diff, Acceptance Criteria, Risks, and Rollback.\nExecute the Plan. Use Bundle References (TaskGet) for deeper context if needed.\n\n## End of Work Protocol (MANDATORY)\nTaskUpdate(taskId: '<task-5-id>', status: 'completed', description: '<your implementation report>')\nDo NOT go idle without calling TaskUpdate.")
|
|
154
154
|
```
|
|
155
155
|
10. Wait for implementation — poll `TaskList` until task 5 is `status: "completed"`
|
|
156
|
-
11. Read final report from `TaskGet(task-5-id).description` →
|
|
156
|
+
11. Read final report from `TaskGet(task-5-id).description` → Call `TeamDelete`. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
@@ -87,7 +87,7 @@ $ARGUMENTS
|
|
|
87
87
|
- `architect-brief.md`
|
|
88
88
|
- `code-analyst-brief.md`
|
|
89
89
|
- `context-curator-brief.md`
|
|
90
|
-
11. **Clean shutdown** —
|
|
90
|
+
11. **Clean shutdown** — Call `TeamDelete`. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
91
91
|
12. **Report** — summarize what was generated: 5 codebase analysis files in `.legion/codebase/`, 3 agent briefs in `.legion/codebase/agents/`, and key findings stored in MCP memory
|
|
92
92
|
|
|
93
93
|
## Rules
|
package/commands/legion/cycle.md
CHANGED
|
@@ -111,7 +111,7 @@ $ARGUMENTS
|
|
|
111
111
|
TaskUpdate(taskId: "<your-task-id>", status: "completed", description: "<your implementation report>")
|
|
112
112
|
```
|
|
113
113
|
10. **Wait** for implementation — poll `TaskList` until task 5 is `status: "completed"`
|
|
114
|
-
11. **Clean shutdown** —
|
|
114
|
+
11. **Clean shutdown** — Call `TeamDelete`. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
115
115
|
12. **Report** — read final report from `TaskGet` on task 5, summarize what was done to the user
|
|
116
116
|
|
|
117
117
|
## Rules
|
package/commands/legion/quick.md
CHANGED
|
@@ -82,7 +82,7 @@ $ARGUMENTS
|
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
8. **Monitor** — poll `TaskList` until Task 3 is `status: "completed"`
|
|
85
|
-
9. **Clean shutdown** —
|
|
85
|
+
9. **Clean shutdown** — Call `TeamDelete`. Optionally send `shutdown_request` to teammates as best-effort, but do NOT wait for `shutdown_response`. Idle agents do not process incoming messages.
|
|
86
86
|
10. **Report** — read final report from `TaskGet` on Task 3, summarize what was done to the user
|
|
87
87
|
|
|
88
88
|
## Rules
|
|
@@ -93,6 +93,13 @@ function systemNotify(title, message) {
|
|
|
93
93
|
} else if (platform === 'linux') {
|
|
94
94
|
spawnSync('notify-send', ['--urgency=critical', title, message],
|
|
95
95
|
{ timeout: 3000, stdio: 'ignore' });
|
|
96
|
+
} else if (platform === 'win32') {
|
|
97
|
+
const safeMsg = message.replace(/'/g, "''");
|
|
98
|
+
const safeTitle = title.replace(/'/g, "''");
|
|
99
|
+
const ps = `Add-Type -AssemblyName System.Windows.Forms; ` +
|
|
100
|
+
`[System.Windows.Forms.MessageBox]::Show('${safeMsg}', '${safeTitle}')`;
|
|
101
|
+
spawnSync('powershell', ['-NonInteractive', '-Command', ps],
|
|
102
|
+
{ timeout: 3000, stdio: 'ignore' });
|
|
96
103
|
}
|
|
97
104
|
} catch (_e) { /* best-effort */ }
|
|
98
105
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// MCP & Subagent Advisor — Legion SessionStart
|
|
2
|
+
// MCP & Subagent Advisor — Legion SessionStart hook
|
|
3
3
|
//
|
|
4
4
|
// Reads .legion/config.json and injects MCP server awareness + subagent
|
|
5
5
|
// enforcement into agent context. Searches for config up the directory tree.
|
|
6
6
|
//
|
|
7
|
-
// Events: SessionStart (matcher: "startup")
|
|
7
|
+
// Events: SessionStart (matcher: "startup")
|
|
8
8
|
// Output: hookSpecificOutput.additionalContext with MCP + subagent rules
|
|
9
9
|
|
|
10
10
|
'use strict';
|
|
@@ -57,6 +57,13 @@ process.stdin.on('end', () => {
|
|
|
57
57
|
process.exit(0);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
// Only inject enforcement on SessionStart — NOT on SubagentStart
|
|
61
|
+
// to prevent recursive subagent spawning loops
|
|
62
|
+
const hookEvent = data.hook_event_name || 'SessionStart';
|
|
63
|
+
if (hookEvent === 'SubagentStart') {
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
const parts = [];
|
|
61
68
|
|
|
62
69
|
// ── MCP enforcement ───────────────────────────────────────────────────
|
|
@@ -90,23 +97,23 @@ process.stdin.on('end', () => {
|
|
|
90
97
|
|
|
91
98
|
// ── Subagent enforcement ──────────────────────────────────────────────
|
|
92
99
|
if (config.subagents && config.subagents.enforce !== false) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
100
|
+
const sa = config.subagents;
|
|
101
|
+
const minCount = sa.minCount || 3;
|
|
102
|
+
const types = Array.isArray(sa.types) ? sa.types : [];
|
|
103
|
+
const saMessage = sa.message ||
|
|
104
|
+
'ALWAYS delegate tasks to subagents via Task tool.';
|
|
105
|
+
|
|
106
|
+
let saContext =
|
|
107
|
+
`[LEGION SUBAGENTS] ${saMessage} ` +
|
|
108
|
+
`Minimum ${minCount} subagents per task. ` +
|
|
109
|
+
'Use Task tool with specialized subagent_type for each subtask. ' +
|
|
110
|
+
'Maximize parallel execution — launch independent agents simultaneously.';
|
|
111
|
+
|
|
112
|
+
if (types.length > 0) {
|
|
113
|
+
saContext += ` Recommended types: ${types.join(', ')}.`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
parts.push(saContext);
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
// ── Output ────────────────────────────────────────────────────────────
|
|
@@ -114,8 +121,6 @@ process.stdin.on('end', () => {
|
|
|
114
121
|
process.exit(0);
|
|
115
122
|
}
|
|
116
123
|
|
|
117
|
-
const hookEvent = data.hook_event_name || 'SessionStart';
|
|
118
|
-
|
|
119
124
|
const output = {
|
|
120
125
|
hookSpecificOutput: {
|
|
121
126
|
hookEventName: hookEvent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "legion-cc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "Legion — context monitoring hooks and agent teams for Claude Code",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"README.md"
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
|
-
"postinstall": "node bin/install.js
|
|
18
|
+
"postinstall": "node bin/install.js || exit 0"
|
|
19
19
|
},
|
|
20
20
|
"author": "Vladyslav Blackmoore",
|
|
21
21
|
"repository": {
|