@synergenius/flow-weaver-pack-weaver 0.9.62 → 0.9.78

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 (162) hide show
  1. package/dist/ai-chat-provider.d.ts +12 -0
  2. package/dist/ai-chat-provider.d.ts.map +1 -1
  3. package/dist/ai-chat-provider.js +173 -19
  4. package/dist/ai-chat-provider.js.map +1 -1
  5. package/dist/bot/agent-loop.d.ts +20 -0
  6. package/dist/bot/agent-loop.d.ts.map +1 -0
  7. package/dist/bot/agent-loop.js +331 -0
  8. package/dist/bot/agent-loop.js.map +1 -0
  9. package/dist/bot/ai-router.d.ts +19 -0
  10. package/dist/bot/ai-router.d.ts.map +1 -0
  11. package/dist/bot/ai-router.js +104 -0
  12. package/dist/bot/ai-router.js.map +1 -0
  13. package/dist/bot/bot-registry.js +2 -2
  14. package/dist/bot/bot-registry.js.map +1 -1
  15. package/dist/bot/conversation-store.d.ts +1 -0
  16. package/dist/bot/conversation-store.d.ts.map +1 -1
  17. package/dist/bot/conversation-store.js.map +1 -1
  18. package/dist/bot/improve-loop.js.map +1 -1
  19. package/dist/bot/instance-manager.d.ts +31 -0
  20. package/dist/bot/instance-manager.d.ts.map +1 -0
  21. package/dist/bot/instance-manager.js +115 -0
  22. package/dist/bot/instance-manager.js.map +1 -0
  23. package/dist/bot/orchestrator.d.ts +36 -0
  24. package/dist/bot/orchestrator.d.ts.map +1 -0
  25. package/dist/bot/orchestrator.js +176 -0
  26. package/dist/bot/orchestrator.js.map +1 -0
  27. package/dist/bot/profile-store.d.ts +36 -0
  28. package/dist/bot/profile-store.d.ts.map +1 -0
  29. package/dist/bot/profile-store.js +208 -0
  30. package/dist/bot/profile-store.js.map +1 -0
  31. package/dist/bot/profile-types.d.ts +126 -0
  32. package/dist/bot/profile-types.d.ts.map +1 -0
  33. package/dist/bot/profile-types.js +7 -0
  34. package/dist/bot/profile-types.js.map +1 -0
  35. package/dist/bot/session-state.d.ts +25 -0
  36. package/dist/bot/session-state.d.ts.map +1 -0
  37. package/dist/bot/session-state.js +110 -0
  38. package/dist/bot/session-state.js.map +1 -0
  39. package/dist/bot/swarm-controller.d.ts +37 -21
  40. package/dist/bot/swarm-controller.d.ts.map +1 -1
  41. package/dist/bot/swarm-controller.js +344 -163
  42. package/dist/bot/swarm-controller.js.map +1 -1
  43. package/dist/bot/task-prompt-builder.d.ts +2 -1
  44. package/dist/bot/task-prompt-builder.d.ts.map +1 -1
  45. package/dist/bot/task-prompt-builder.js +33 -10
  46. package/dist/bot/task-prompt-builder.js.map +1 -1
  47. package/dist/bot/task-queue.d.ts +46 -0
  48. package/dist/bot/task-queue.d.ts.map +1 -0
  49. package/dist/bot/task-queue.js +237 -0
  50. package/dist/bot/task-queue.js.map +1 -0
  51. package/dist/bot/task-store.d.ts +1 -6
  52. package/dist/bot/task-store.d.ts.map +1 -1
  53. package/dist/bot/task-store.js +27 -78
  54. package/dist/bot/task-store.js.map +1 -1
  55. package/dist/bot/task-types.d.ts +8 -4
  56. package/dist/bot/task-types.d.ts.map +1 -1
  57. package/dist/cli-handlers.d.ts.map +1 -1
  58. package/dist/cli-handlers.js +2 -3
  59. package/dist/cli-handlers.js.map +1 -1
  60. package/dist/cli.d.ts +3 -0
  61. package/dist/cli.d.ts.map +1 -0
  62. package/dist/cli.js +749 -0
  63. package/dist/cli.js.map +1 -0
  64. package/dist/docs/docs/weaver-bot-usage.md +35 -18
  65. package/dist/docs/docs/weaver-config.md +20 -0
  66. package/dist/docs/docs/weaver-task-queue.md +31 -19
  67. package/dist/docs/weaver-config.md +15 -9
  68. package/dist/mcp-tools.d.ts +17 -0
  69. package/dist/mcp-tools.d.ts.map +1 -1
  70. package/dist/mcp-tools.js +98 -232
  71. package/dist/mcp-tools.js.map +1 -1
  72. package/dist/node-types/orchestrator-dispatch.d.ts +17 -0
  73. package/dist/node-types/orchestrator-dispatch.d.ts.map +1 -0
  74. package/dist/node-types/orchestrator-dispatch.js +63 -0
  75. package/dist/node-types/orchestrator-dispatch.js.map +1 -0
  76. package/dist/node-types/orchestrator-load-state.d.ts +16 -0
  77. package/dist/node-types/orchestrator-load-state.d.ts.map +1 -0
  78. package/dist/node-types/orchestrator-load-state.js +60 -0
  79. package/dist/node-types/orchestrator-load-state.js.map +1 -0
  80. package/dist/node-types/orchestrator-route.d.ts +16 -0
  81. package/dist/node-types/orchestrator-route.d.ts.map +1 -0
  82. package/dist/node-types/orchestrator-route.js +28 -0
  83. package/dist/node-types/orchestrator-route.js.map +1 -0
  84. package/dist/node-types/receive-task.d.ts +2 -3
  85. package/dist/node-types/receive-task.d.ts.map +1 -1
  86. package/dist/node-types/receive-task.js +3 -28
  87. package/dist/node-types/receive-task.js.map +1 -1
  88. package/dist/templates/weaver-template.d.ts +11 -0
  89. package/dist/templates/weaver-template.d.ts.map +1 -0
  90. package/dist/templates/weaver-template.js +53 -0
  91. package/dist/templates/weaver-template.js.map +1 -0
  92. package/dist/ui/bot-constants.d.ts +14 -0
  93. package/dist/ui/bot-constants.d.ts.map +1 -0
  94. package/dist/ui/bot-constants.js +189 -0
  95. package/dist/ui/bot-constants.js.map +1 -0
  96. package/dist/ui/bot-panel.js +51 -90
  97. package/dist/ui/bot-slot-card.js +87 -122
  98. package/dist/ui/budget-bar.js +5 -3
  99. package/dist/ui/chat-task-result.js +4 -7
  100. package/dist/ui/decision-log.js +136 -0
  101. package/dist/ui/profile-card.js +158 -0
  102. package/dist/ui/profile-editor.js +597 -0
  103. package/dist/ui/swarm-controls.js +36 -27
  104. package/dist/ui/swarm-dashboard.js +2034 -736
  105. package/dist/ui/task-create-form.js +39 -116
  106. package/dist/ui/task-detail-view.js +490 -239
  107. package/dist/ui/task-pool-list.js +69 -94
  108. package/dist/workflows/orchestrator.d.ts +21 -0
  109. package/dist/workflows/orchestrator.d.ts.map +1 -0
  110. package/dist/workflows/orchestrator.js +281 -0
  111. package/dist/workflows/orchestrator.js.map +1 -0
  112. package/dist/workflows/weaver-bot-session.d.ts +65 -0
  113. package/dist/workflows/weaver-bot-session.d.ts.map +1 -0
  114. package/dist/workflows/weaver-bot-session.js +68 -0
  115. package/dist/workflows/weaver-bot-session.js.map +1 -0
  116. package/dist/workflows/weaver.d.ts +24 -0
  117. package/dist/workflows/weaver.d.ts.map +1 -0
  118. package/dist/workflows/weaver.js +28 -0
  119. package/dist/workflows/weaver.js.map +1 -0
  120. package/flowweaver.manifest.json +253 -66
  121. package/package.json +1 -1
  122. package/src/ai-chat-provider.ts +184 -18
  123. package/src/bot/ai-router.ts +132 -0
  124. package/src/bot/bot-registry.ts +2 -2
  125. package/src/bot/conversation-store.ts +2 -1
  126. package/src/bot/improve-loop.ts +6 -6
  127. package/src/bot/instance-manager.ts +128 -0
  128. package/src/bot/orchestrator.ts +244 -0
  129. package/src/bot/profile-store.ts +225 -0
  130. package/src/bot/profile-types.ts +141 -0
  131. package/src/bot/swarm-controller.ts +385 -186
  132. package/src/bot/task-prompt-builder.ts +37 -6
  133. package/src/bot/task-store.ts +28 -89
  134. package/src/bot/task-types.ts +10 -4
  135. package/src/cli-handlers.ts +2 -3
  136. package/src/docs/weaver-bot-usage.md +35 -18
  137. package/src/docs/weaver-config.md +20 -0
  138. package/src/docs/weaver-task-queue.md +31 -19
  139. package/src/mcp-tools.ts +129 -320
  140. package/src/node-types/orchestrator-dispatch.ts +71 -0
  141. package/src/node-types/orchestrator-load-state.ts +66 -0
  142. package/src/node-types/orchestrator-route.ts +33 -0
  143. package/src/node-types/receive-task.ts +3 -26
  144. package/src/ui/bot-constants.ts +192 -0
  145. package/src/ui/bot-panel.tsx +55 -79
  146. package/src/ui/bot-slot-card.tsx +69 -117
  147. package/src/ui/budget-bar.tsx +5 -3
  148. package/src/ui/chat-task-result.tsx +6 -9
  149. package/src/ui/decision-log.tsx +148 -0
  150. package/src/ui/profile-card.tsx +157 -0
  151. package/src/ui/profile-editor.tsx +384 -0
  152. package/src/ui/swarm-controls.tsx +35 -31
  153. package/src/ui/swarm-dashboard.tsx +409 -80
  154. package/src/ui/task-create-form.tsx +29 -119
  155. package/src/ui/task-detail-view.tsx +461 -215
  156. package/src/ui/task-pool-list.tsx +74 -95
  157. package/src/workflows/orchestrator.ts +302 -0
  158. package/dist/docs/weaver-bot-usage.md +0 -34
  159. package/dist/docs/weaver-genesis.md +0 -32
  160. package/dist/docs/weaver-task-queue.md +0 -34
  161. package/src/bot/error-guide.ts +0 -4
  162. package/src/bot/retry-utils.ts +0 -4
@@ -18,6 +18,7 @@
18
18
  */
19
19
 
20
20
  import type { Task, RunSummary } from './task-types.js';
21
+ import type { ProfilePreferences } from './profile-types.js';
21
22
 
22
23
  const MAX_CONTEXT_TOKENS = 4000;
23
24
  const CHARS_PER_TOKEN = 4; // rough estimate
@@ -28,16 +29,17 @@ export function buildTaskPrompt(
28
29
  task: Task,
29
30
  parentTask?: Task | null,
30
31
  siblingTasks?: Task[],
32
+ preferences?: ProfilePreferences,
31
33
  ): string {
32
34
  // Build the full (un-truncated) prompt first
33
- const prompt = buildFull(task, parentTask, siblingTasks);
35
+ const prompt = buildFull(task, parentTask, siblingTasks, preferences);
34
36
 
35
37
  if (prompt.length <= MAX_CONTEXT_CHARS) {
36
38
  return prompt;
37
39
  }
38
40
 
39
41
  // Over budget — apply truncation cascade progressively
40
- return truncatePrompt(task, parentTask, siblingTasks);
42
+ return truncatePrompt(task, parentTask, siblingTasks, preferences);
41
43
  }
42
44
 
43
45
  // ---------------------------------------------------------------------------
@@ -48,6 +50,7 @@ function buildFull(
48
50
  task: Task,
49
51
  parentTask?: Task | null,
50
52
  siblingTasks?: Task[],
53
+ preferences?: ProfilePreferences,
51
54
  ): string {
52
55
  const sections: string[] = [];
53
56
 
@@ -88,6 +91,11 @@ function buildFull(
88
91
  sections.push(`### Last Error\n${task.context.lastError}`);
89
92
  }
90
93
 
94
+ // Execution preferences
95
+ if (preferences) {
96
+ sections.push(buildPreferencesSection(preferences));
97
+ }
98
+
91
99
  // Parent context
92
100
  if (parentTask) {
93
101
  sections.push(buildParentSection(parentTask, siblingTasks));
@@ -104,6 +112,7 @@ function truncatePrompt(
104
112
  task: Task,
105
113
  parentTask?: Task | null,
106
114
  siblingTasks?: Task[],
115
+ preferences?: ProfilePreferences,
107
116
  ): string {
108
117
  // Level 1: All summaries condensed to one-liners
109
118
  let result = buildWithTruncation(task, parentTask, siblingTasks, {
@@ -111,7 +120,7 @@ function truncatePrompt(
111
120
  filesFromRecentRunsOnly: false,
112
121
  parentTitleOnly: false,
113
122
  notesCapped: false,
114
- });
123
+ }, preferences);
115
124
  if (result.length <= MAX_CONTEXT_CHARS) return result;
116
125
 
117
126
  // Level 2: File list → only files from last 2 runs
@@ -120,7 +129,7 @@ function truncatePrompt(
120
129
  filesFromRecentRunsOnly: true,
121
130
  parentTitleOnly: false,
122
131
  notesCapped: false,
123
- });
132
+ }, preferences);
124
133
  if (result.length <= MAX_CONTEXT_CHARS) return result;
125
134
 
126
135
  // Level 3: Parent context → title only
@@ -129,7 +138,7 @@ function truncatePrompt(
129
138
  filesFromRecentRunsOnly: true,
130
139
  parentTitleOnly: true,
131
140
  notesCapped: false,
132
- });
141
+ }, preferences);
133
142
  if (result.length <= MAX_CONTEXT_CHARS) return result;
134
143
 
135
144
  // Level 4: Notes → first 500 chars
@@ -138,7 +147,7 @@ function truncatePrompt(
138
147
  filesFromRecentRunsOnly: true,
139
148
  parentTitleOnly: true,
140
149
  notesCapped: true,
141
- });
150
+ }, preferences);
142
151
 
143
152
  // Hard-truncate if still over (shouldn't happen with reasonable data)
144
153
  if (result.length > MAX_CONTEXT_CHARS) {
@@ -160,6 +169,7 @@ function buildWithTruncation(
160
169
  parentTask: Task | null | undefined,
161
170
  siblingTasks: Task[] | undefined,
162
171
  flags: TruncationFlags,
172
+ preferences?: ProfilePreferences,
163
173
  ): string {
164
174
  const sections: string[] = [];
165
175
 
@@ -215,6 +225,11 @@ function buildWithTruncation(
215
225
  sections.push(`### Last Error\n${errorText}`);
216
226
  }
217
227
 
228
+ // Execution preferences
229
+ if (preferences) {
230
+ sections.push(buildPreferencesSection(preferences));
231
+ }
232
+
218
233
  // Parent context
219
234
  if (parentTask) {
220
235
  if (flags.parentTitleOnly) {
@@ -264,6 +279,22 @@ function buildParentSection(
264
279
  return section;
265
280
  }
266
281
 
282
+ function buildPreferencesSection(preferences: ProfilePreferences): string {
283
+ const lines = ['## Execution Preferences'];
284
+ lines.push(`Cost strategy: ${preferences.costStrategy}`);
285
+ if (preferences.maxCostPerRun !== undefined) {
286
+ lines.push(`Max cost per run: $${preferences.maxCostPerRun.toFixed(2)}`);
287
+ }
288
+ if (preferences.maxCostPerTask !== undefined) {
289
+ lines.push(`Max cost per task: $${preferences.maxCostPerTask.toFixed(2)}`);
290
+ }
291
+ if (preferences.instructions) {
292
+ lines.push(`Instructions: ${preferences.instructions}`);
293
+ }
294
+ lines.push(`Approval required: ${preferences.requireApproval ? 'yes' : 'no'}`);
295
+ return lines.join('\n');
296
+ }
297
+
267
298
  function statusIcon(status: string): string {
268
299
  switch (status) {
269
300
  case 'done':
@@ -2,7 +2,7 @@ import * as fs from 'node:fs';
2
2
  import * as path from 'node:path';
3
3
  import * as crypto from 'node:crypto';
4
4
  import { AsyncMutex } from './async-mutex.js';
5
- import type { Task, TaskFilter, CreateTaskInput, RunSummary, TaskStatus } from './task-types.js';
5
+ import type { Task, TaskFilter, CreateTaskInput, RunSummary } from './task-types.js';
6
6
 
7
7
  /** Don't re-queue tasks completed/failed within this window (ms). */
8
8
  const DEDUP_WINDOW_MS = 3_600_000; // 1 hour
@@ -43,8 +43,8 @@ export class TaskStore {
43
43
  isParent: true,
44
44
  parentId: input.parentId,
45
45
  dependsOn: input.dependsOn ?? [],
46
- assignedBots: input.assignedBots ?? [],
47
46
  currentBotId: undefined,
47
+ currentRunId: undefined,
48
48
  context: { files: [], notes: '', runSummaries: [] },
49
49
  runs: [],
50
50
  attempt: 0,
@@ -54,6 +54,8 @@ export class TaskStore {
54
54
  tokensUsed: 0,
55
55
  costUsed: 0,
56
56
  timeoutMs: input.timeoutMs,
57
+ complexity: input.complexity,
58
+ assignedProfile: input.assignedProfile,
57
59
  createdBy: input.createdBy ?? 'user',
58
60
  createdAt: now,
59
61
  updatedAt: now,
@@ -80,8 +82,8 @@ export class TaskStore {
80
82
  isParent: false,
81
83
  parentId: parentId,
82
84
  dependsOn: resolvedDeps,
83
- assignedBots: sub.assignedBots ?? input.assignedBots ?? [],
84
85
  currentBotId: undefined,
86
+ currentRunId: undefined,
85
87
  context: { files: [], notes: '', runSummaries: [] },
86
88
  runs: [],
87
89
  attempt: 0,
@@ -90,6 +92,8 @@ export class TaskStore {
90
92
  budgetCost: input.budgetCost,
91
93
  tokensUsed: 0,
92
94
  costUsed: 0,
95
+ complexity: sub.complexity ?? input.complexity,
96
+ assignedProfile: sub.assignedProfile ?? input.assignedProfile,
93
97
  createdBy: input.createdBy ?? 'user',
94
98
  createdAt: now,
95
99
  updatedAt: now,
@@ -116,8 +120,8 @@ export class TaskStore {
116
120
  isParent: false,
117
121
  parentId: input.parentId,
118
122
  dependsOn: input.dependsOn ?? [],
119
- assignedBots: input.assignedBots ?? [],
120
123
  currentBotId: undefined,
124
+ currentRunId: undefined,
121
125
  context: { files: [], notes: '', runSummaries: [] },
122
126
  runs: [],
123
127
  attempt: 0,
@@ -127,6 +131,8 @@ export class TaskStore {
127
131
  tokensUsed: 0,
128
132
  costUsed: 0,
129
133
  timeoutMs: input.timeoutMs,
134
+ complexity: input.complexity,
135
+ assignedProfile: input.assignedProfile,
130
136
  createdBy: input.createdBy ?? 'user',
131
137
  createdAt: now,
132
138
  updatedAt: now,
@@ -159,11 +165,6 @@ export class TaskStore {
159
165
  if (filter.botId !== undefined) {
160
166
  tasks = tasks.filter(t => t.currentBotId === filter.botId);
161
167
  }
162
- if (filter.assignedBots !== undefined && filter.assignedBots.length > 0) {
163
- tasks = tasks.filter(t =>
164
- t.assignedBots.length === 0 || t.assignedBots.some(b => filter.assignedBots!.includes(b)),
165
- );
166
- }
167
168
  if (filter.limit !== undefined && filter.limit > 0) {
168
169
  tasks = tasks.slice(0, filter.limit);
169
170
  }
@@ -221,57 +222,31 @@ export class TaskStore {
221
222
  }
222
223
 
223
224
  // ---------------------------------------------------------------------------
224
- // Atomic claim
225
+ // Push-based assignment (orchestrator)
225
226
  // ---------------------------------------------------------------------------
226
227
 
227
- async claimNext(botId: string): Promise<Task | null> {
228
+ async assignToInstance(taskId: string, instanceId: string, profileId: string): Promise<Task> {
228
229
  return this.mutex.runExclusive(async () => {
229
230
  const tasks = this._readAll();
231
+ const idx = tasks.findIndex(t => t.id === taskId);
232
+ if (idx === -1) throw new Error(`Task not found: ${taskId}`);
230
233
 
231
- // Build a set of done task IDs for dependency checks
232
- const doneIds = new Set(tasks.filter(t => t.status === 'done').map(t => t.id));
233
-
234
- // Find eligible tasks
235
- const eligible = tasks.filter(t => {
236
- // Must be pending, or failed with retries left
237
- if (t.status === 'pending') { /* ok */ }
238
- else if (t.status === 'failed' && t.attempt < t.maxAttempts) { /* ok */ }
239
- else return false;
240
-
241
- // Skip parent tasks
242
- if (t.isParent) return false;
243
-
244
- // Check assigned bots
245
- if (t.assignedBots.length > 0 && !t.assignedBots.includes(botId)) return false;
246
-
247
- // Check dependencies — all must be done
248
- if (t.dependsOn.length > 0 && !t.dependsOn.every(depId => doneIds.has(depId))) return false;
249
-
250
- // Check per-task budget (tokens)
251
- if (t.budgetTokens !== undefined && t.tokensUsed >= t.budgetTokens) return false;
252
-
253
- // Check per-task budget (cost)
254
- if (t.budgetCost !== undefined && t.costUsed >= t.budgetCost) return false;
255
-
256
- return true;
257
- });
258
-
259
- if (eligible.length === 0) return null;
260
-
261
- // Sort: higher priority first, then older createdAt first
262
- eligible.sort((a, b) =>
263
- b.priority - a.priority || Date.parse(a.createdAt) - Date.parse(b.createdAt),
264
- );
265
-
266
- const target = eligible[0];
267
- const idx = tasks.findIndex(t => t.id === target.id);
234
+ const task = tasks[idx];
235
+ const assignable =
236
+ task.status === 'pending' ||
237
+ (task.status === 'failed' && task.attempt < task.maxAttempts);
238
+ if (!assignable) {
239
+ throw new Error(`Task ${taskId} is not assignable (status: ${task.status}, attempt: ${task.attempt}/${task.maxAttempts})`);
240
+ }
268
241
 
269
- tasks[idx].status = 'in-progress';
270
- tasks[idx].currentBotId = botId;
271
- tasks[idx].updatedAt = new Date().toISOString();
242
+ task.status = 'in-progress';
243
+ task.currentBotId = instanceId;
244
+ task.assignedProfile = profileId;
245
+ task.updatedAt = new Date().toISOString();
272
246
 
247
+ tasks[idx] = task;
273
248
  this._writeAll(tasks);
274
- return tasks[idx];
249
+ return task;
275
250
  });
276
251
  }
277
252
 
@@ -303,6 +278,7 @@ export class TaskStore {
303
278
  task.attempt += 1;
304
279
  task.status = status;
305
280
  task.currentBotId = undefined;
281
+ task.currentRunId = undefined;
306
282
  task.updatedAt = new Date().toISOString();
307
283
 
308
284
  if (status === 'done') {
@@ -408,43 +384,6 @@ export class TaskStore {
408
384
  return null;
409
385
  }
410
386
 
411
- // ---------------------------------------------------------------------------
412
- // Legacy migration
413
- // ---------------------------------------------------------------------------
414
-
415
- /**
416
- * Migrate legacy TaskQueue entries to Task entities.
417
- * Called once on first load. Renames legacy files after migration.
418
- */
419
- async migrate(): Promise<void> {
420
- const legacyQueuePath = path.join(this.projectDir, '.weaver', 'task-queue.ndjson');
421
- const legacySessionPath = path.join(this.projectDir, '.weaver', 'session.json');
422
-
423
- // Migrate task queue
424
- if (fs.existsSync(legacyQueuePath)) {
425
- const lines = fs.readFileSync(legacyQueuePath, 'utf-8').split('\n').filter(Boolean);
426
- for (const line of lines) {
427
- try {
428
- const entry = JSON.parse(line);
429
- if (entry.status === 'pending') {
430
- await this.create({
431
- title: entry.instruction,
432
- description: entry.instruction,
433
- priority: entry.priority ?? 0,
434
- createdBy: 'user',
435
- });
436
- }
437
- } catch { /* skip corrupt lines */ }
438
- }
439
- fs.renameSync(legacyQueuePath, legacyQueuePath + '.migrated');
440
- }
441
-
442
- // Discard legacy session
443
- if (fs.existsSync(legacySessionPath)) {
444
- fs.renameSync(legacySessionPath, legacySessionPath + '.migrated');
445
- }
446
- }
447
-
448
387
  // ---------------------------------------------------------------------------
449
388
  // File I/O — atomic write via temp + rename
450
389
  // ---------------------------------------------------------------------------
@@ -37,8 +37,8 @@ export interface Task {
37
37
  dependsOn: string[];
38
38
 
39
39
  // Assignment
40
- assignedBots: string[];
41
40
  currentBotId?: string;
41
+ currentRunId?: string;
42
42
 
43
43
  // Context
44
44
  context: TaskContext;
@@ -57,6 +57,11 @@ export interface Task {
57
57
  // Timeout
58
58
  timeoutMs?: number;
59
59
 
60
+ // Orchestrator routing
61
+ assignedProfile?: string; // profile ID assigned by orchestrator
62
+ routingReason?: string; // why this profile was chosen
63
+ complexity?: 'trivial' | 'simple' | 'moderate' | 'complex'; // task complexity estimate
64
+
60
65
  // Metadata
61
66
  createdBy: 'user' | 'ai';
62
67
  createdAt: string;
@@ -68,14 +73,12 @@ export interface TaskFilter {
68
73
  status?: TaskStatus | TaskStatus[];
69
74
  parentId?: string;
70
75
  botId?: string;
71
- assignedBots?: string[];
72
76
  limit?: number;
73
77
  }
74
78
 
75
79
  export interface CreateTaskInput {
76
80
  title: string;
77
81
  description: string;
78
- assignedBots?: string[];
79
82
  priority?: number;
80
83
  parentId?: string;
81
84
  dependsOn?: string[];
@@ -84,11 +87,14 @@ export interface CreateTaskInput {
84
87
  timeoutMs?: number;
85
88
  maxAttempts?: number;
86
89
  createdBy?: 'user' | 'ai';
90
+ complexity?: 'trivial' | 'simple' | 'moderate' | 'complex';
91
+ assignedProfile?: string;
87
92
  subtasks?: Array<{
88
93
  title: string;
89
94
  description?: string;
90
- assignedBots?: string[];
91
95
  dependsOn?: string[];
92
96
  priority?: number;
97
+ complexity?: 'trivial' | 'simple' | 'moderate' | 'complex';
98
+ assignedProfile?: string;
93
99
  }>;
94
100
  }
@@ -1447,11 +1447,10 @@ export async function handleSession(opts: ParsedArgs): Promise<void> {
1447
1447
  const filesInUse = new Set<string>();
1448
1448
 
1449
1449
  const processTask = async (task: { id: string; title: string; description: string; context: { files: string[] } }) => {
1450
- // Map to legacy format for workflow runner
1451
- const legacyTask = { id: task.id, instruction: task.title, targets: task.context.files };
1450
+ const taskPayload = { id: task.id, instruction: task.title, description: task.description, targets: task.context.files };
1452
1451
  try {
1453
1452
  const result = await runWorkflow(workflowPath, {
1454
- params: { projectDir, taskJson: JSON.stringify(legacyTask) },
1453
+ params: { projectDir, taskJson: JSON.stringify(taskPayload) },
1455
1454
  verbose: opts.verbose,
1456
1455
  dryRun: opts.dryRun,
1457
1456
  config,
@@ -1,34 +1,51 @@
1
- ## Weaver Bot
1
+ ## Weaver Bot (Swarm)
2
2
 
3
- The Weaver bot is an autonomous AI agent that creates and modifies Flow Weaver workflows from natural language instructions.
3
+ The Weaver bot is an autonomous AI agent that creates and modifies Flow Weaver workflows. Tasks are executed via the swarm orchestrator, which routes work to the best available bot profile.
4
4
 
5
- ### Running the bot
5
+ ### Running tasks
6
6
 
7
- Use `fw_weaver_bot` with a task description:
8
- - `task`: Natural language instruction (required)
9
- - `mode`: `create` (new workflow), `modify` (edit existing), `read` (analyze), `batch` (multiple tasks)
10
- - `targets`: File paths for modify/read mode
11
- - `autoApprove`: Skip the approval gate (default: true in studio)
7
+ Use `fw_weaver_task_create` to submit work:
8
+ - `title`: Short task title (required)
9
+ - `description`: Detailed instructions
10
+ - `assignedProfile`: Target a specific bot profile
11
+ - `complexity`: trivial, simple, moderate, complex
12
+ - `subtasks`: Inline subtask definitions with dependency chaining
13
+
14
+ Then start the swarm with `fw_weaver_swarm_start` to begin execution.
12
15
 
13
16
  ### Execution flow
14
17
 
15
- 1. **Receive task** — parses instruction and determines mode
16
- 2. **Build context** — gathers project state, templates, and relevant files
17
- 3. **Plan** — AI generates a step-by-step execution plan
18
- 4. **Approval gate** — plan shown for review (skipped if autoApprove)
19
- 5. **Execute + validate + retry** — runs steps, validates output, retries on errors (up to 3 attempts)
18
+ 1. **Create task** — `fw_weaver_task_create` adds task to the pool
19
+ 2. **Orchestrator routes** — matches task to best bot profile via fast-path cascade (exact-match, capability-match, single-eligible, ai-routed, round-robin)
20
+ 3. **Build context** — gathers project state, templates, and relevant files
21
+ 4. **Plan** — AI generates a step-by-step execution plan
22
+ 5. **Execute + validate + retry** — runs steps, validates output, retries on errors (up to maxAttempts)
20
23
  6. **Git ops** — commits changes if successful
21
- 7. **Report** — returns summary with outcome
24
+ 7. **Report** — task marked done/failed with run summary
22
25
 
23
26
  ### Steering a running bot
24
27
 
25
- Use `fw_weaver_steer` to control execution:
28
+ Use `fw_weaver_steer` with a `botId` to control execution:
26
29
  - `pause` — pause at next safe point
27
30
  - `resume` — continue after pause
28
31
  - `cancel` — abort execution
29
- - `redirect` — change task mid-execution
30
- - `queue` — add a follow-up task
31
32
 
32
33
  ### Checking status
33
34
 
34
- Use `fw_weaver_status` to see the current bot session state, active task, and completion count.
35
+ - `fw_weaver_status` quick swarm summary (active bots, tasks completed, budget)
36
+ - `fw_weaver_swarm_status` — full swarm state with per-instance details
37
+ - `fw_weaver_swarm_events` — live event stream
38
+ - `fw_weaver_orchestrator_status` — routing decisions, stats, active instances
39
+
40
+ ### Profiles
41
+
42
+ Use `fw_weaver_profile_create` to create specialized bot profiles. Each profile defines:
43
+
44
+ - **capabilities** — free-form list of `{ name, description }` objects describing what the profile can do. Names are arbitrary strings (e.g. `code-generation`, `testing`, `deployment`). The orchestrator uses the description text to match tasks to profiles.
45
+ - **preferences** — intent-based settings that control profile behavior:
46
+ - `costStrategy` — `"economy"` (minimize cost), `"balanced"` (default), or `"quality"` (maximize quality regardless of cost)
47
+ - `requireApproval` — whether tasks routed to this profile need human approval before execution
48
+ - `instructions` — optional free-text instructions appended to the bot's system prompt
49
+ - **scaling** — `minInstances` and `maxInstances` control how many concurrent bots can run this profile
50
+
51
+ The orchestrator routes tasks to profiles based on `assignedProfile` or by matching task intent against profile capabilities.
@@ -4,6 +4,17 @@ The weaver bot runs workflows, executes tasks from natural language, and evolves
4
4
 
5
5
  The bot has deep knowledge of the full flow-weaver ecosystem: annotation grammar, CLI tools, node patterns, error diagnosis, and the genesis protocol (loaded dynamically from `@synergenius/flow-weaver/doc-metadata`).
6
6
 
7
+ ## Execution models
8
+
9
+ Weaver supports two execution models:
10
+
11
+ - **Single-run mode** — execute one workflow or natural-language task end-to-end via `flow-weaver weaver run` or `flow-weaver weaver bot`. Good for one-off tasks, CI pipelines, and simple automations.
12
+ - **Swarm/task model** — create tasks, define bot profiles with capabilities, and let the orchestrator route work to the best available bot instance. Multiple bots can run concurrently with budget controls and automatic retries.
13
+
14
+ The `.weaver.json` config applies to both models. Provider settings, approval gates, and notifications are shared. Swarm-specific settings (profiles, budgets, concurrency) are managed through the swarm control tools or the Studio UI.
15
+
16
+ > See [weaver-bot-usage.md](weaver-bot-usage.md) for full swarm documentation including profiles, orchestrator routing, and multi-bot workflows.
17
+
7
18
  ## Getting started
8
19
 
9
20
  Run the bot directly via CLI:
@@ -16,6 +27,15 @@ flow-weaver weaver session
16
27
 
17
28
  Or scaffold a project via `flow-weaver init` and select the "AI Workflow Runner" use case.
18
29
 
30
+ ## Profiles and .weaver.json
31
+
32
+ Bot profiles define specialized bot types with free-form capabilities, intent-based preferences, and scaling limits. Profiles are created via `fw_weaver_profile_create` and stored in the `.weaver/` directory. The `.weaver.json` config provides the base provider and approval settings that profiles inherit unless overridden.
33
+
34
+ Each profile specifies:
35
+ - **capabilities** — an array of `{ name, description }` objects. Names are free-form strings (e.g. `code-generation`, `testing`, `deployment`). The orchestrator uses descriptions to match tasks to profiles.
36
+ - **preferences** — intent-based settings: `costStrategy` (`economy`, `balanced`, `quality`), `requireApproval` (boolean), and optional `instructions` (free-text appended to the bot system prompt).
37
+ - **scaling** — `minInstances` / `maxInstances` for concurrency control.
38
+
19
39
  ## .weaver.json
20
40
 
21
41
  Place a `.weaver.json` in your project root to configure the weaver workflow:
@@ -1,34 +1,46 @@
1
- ## Task Queue & Steering
1
+ ## Task Management & Steering
2
2
 
3
- Weaver supports queuing tasks for background processing and steering running bots in real-time.
3
+ Weaver uses a swarm-based task system for background processing and real-time bot control.
4
4
 
5
- ### Task queue
5
+ ### Creating tasks
6
6
 
7
- Use `fw_weaver_queue` to manage tasks:
8
- - `add` — add a task to the queue (requires `task` instruction)
9
- - `list` — show all queued tasks
10
- - `clear` — remove all pending tasks
11
- - `remove` — remove a specific task by ID
7
+ Use `fw_weaver_task_create` to create tasks:
8
+ - `title` — short task title (required)
9
+ - `description` — detailed instructions
10
+ - `priority` — higher number = picked first (default 0)
11
+ - `assignedProfile` — route to a specific bot profile
12
+ - `complexity` — trivial, simple, moderate, complex
13
+ - `subtasks` — inline subtask definitions with `^prev` dependency shorthand
14
+ - `budgetTokens` / `budgetCost` — per-task budget limits
12
15
 
13
- Tasks are stored in NDJSON format and processed sequentially by the bot session.
16
+ ### Listing and managing tasks
17
+
18
+ - `fw_weaver_task_list` — list tasks (filter by status, parentId, botId)
19
+ - `fw_weaver_task_get` — get task details including subtasks
20
+ - `fw_weaver_task_update` — update task fields
21
+ - `fw_weaver_task_cancel` — cancel a pending or running task
22
+ - `fw_weaver_task_retry` — reset a failed task back to pending
14
23
 
15
24
  ### Steering commands
16
25
 
17
- Use `fw_weaver_steer` to control a running bot:
26
+ Use `fw_weaver_steer` to control a running bot instance:
18
27
  - `pause` — pause execution at the next safe point
19
28
  - `resume` — continue after a pause
20
29
  - `cancel` — abort the current task
21
- - `redirect` — change the task instruction mid-execution (requires `payload` with new instruction)
22
- - `queue` — add a follow-up task without interrupting the current one
23
30
 
24
- ### Batch mode
31
+ ### Swarm control
25
32
 
26
- For multiple related tasks, use `fw_weaver_bot` with `mode: "batch"` to process them in sequence through the same bot session, sharing context between tasks.
33
+ - `fw_weaver_swarm_start` start the swarm (spawns bot loops that claim and execute tasks)
34
+ - `fw_weaver_swarm_pause` — pause all bot loops
35
+ - `fw_weaver_swarm_stop` — stop the swarm gracefully
36
+ - `fw_weaver_swarm_status` — full swarm state with per-bot details
37
+ - `fw_weaver_swarm_config` — configure max concurrency, budgets, auto-retry
38
+ - `fw_weaver_swarm_events` — stream swarm-level events for live updates
27
39
 
28
40
  ### Monitoring
29
41
 
30
- Use `fw_weaver_status` to check the current session state:
31
- - Session phase (idle, planning, executing, validating)
32
- - Current task instruction
33
- - Completed task count
34
- - Error state if any
42
+ Use `fw_weaver_status` to check the current swarm state:
43
+ - Swarm phase (idle, running, paused, stopping)
44
+ - Active/total bot instances
45
+ - Tasks completed/failed
46
+ - Budget usage