@synergenius/flow-weaver-pack-weaver 0.9.140 → 0.9.144

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 (85) hide show
  1. package/dist/bot/assistant-tools.d.ts.map +1 -1
  2. package/dist/bot/assistant-tools.js +5 -11
  3. package/dist/bot/assistant-tools.js.map +1 -1
  4. package/dist/bot/behavior-defaults.d.ts +2 -2
  5. package/dist/bot/behavior-defaults.d.ts.map +1 -1
  6. package/dist/bot/behavior-defaults.js +11 -6
  7. package/dist/bot/behavior-defaults.js.map +1 -1
  8. package/dist/bot/capability-registry.d.ts +2 -0
  9. package/dist/bot/capability-registry.d.ts.map +1 -1
  10. package/dist/bot/capability-registry.js +282 -15
  11. package/dist/bot/capability-registry.js.map +1 -1
  12. package/dist/bot/dashboard.js +3 -3
  13. package/dist/bot/dashboard.js.map +1 -1
  14. package/dist/bot/hierarchy-event-log.d.ts +37 -0
  15. package/dist/bot/hierarchy-event-log.d.ts.map +1 -0
  16. package/dist/bot/hierarchy-event-log.js +58 -0
  17. package/dist/bot/hierarchy-event-log.js.map +1 -0
  18. package/dist/bot/operations.d.ts +2 -0
  19. package/dist/bot/operations.d.ts.map +1 -1
  20. package/dist/bot/operations.js +5 -0
  21. package/dist/bot/operations.js.map +1 -1
  22. package/dist/bot/profile-store.d.ts.map +1 -1
  23. package/dist/bot/profile-store.js +46 -0
  24. package/dist/bot/profile-store.js.map +1 -1
  25. package/dist/bot/runner.d.ts.map +1 -1
  26. package/dist/bot/runner.js +51 -16
  27. package/dist/bot/runner.js.map +1 -1
  28. package/dist/bot/step-executor.d.ts.map +1 -1
  29. package/dist/bot/step-executor.js +36 -1
  30. package/dist/bot/step-executor.js.map +1 -1
  31. package/dist/bot/swarm-controller.d.ts +1 -0
  32. package/dist/bot/swarm-controller.d.ts.map +1 -1
  33. package/dist/bot/swarm-controller.js +64 -6
  34. package/dist/bot/swarm-controller.js.map +1 -1
  35. package/dist/bot/task-store.d.ts +1 -1
  36. package/dist/bot/task-store.d.ts.map +1 -1
  37. package/dist/bot/task-store.js +21 -36
  38. package/dist/bot/task-store.js.map +1 -1
  39. package/dist/bot/task-types.d.ts +5 -1
  40. package/dist/bot/task-types.d.ts.map +1 -1
  41. package/dist/bot/types.d.ts +4 -0
  42. package/dist/bot/types.d.ts.map +1 -1
  43. package/dist/node-types/bot-report.d.ts +3 -1
  44. package/dist/node-types/bot-report.d.ts.map +1 -1
  45. package/dist/node-types/bot-report.js +62 -11
  46. package/dist/node-types/bot-report.js.map +1 -1
  47. package/dist/node-types/build-context.d.ts.map +1 -1
  48. package/dist/node-types/build-context.js +32 -0
  49. package/dist/node-types/build-context.js.map +1 -1
  50. package/dist/node-types/report.d.ts +2 -0
  51. package/dist/node-types/report.d.ts.map +1 -1
  52. package/dist/node-types/report.js +61 -7
  53. package/dist/node-types/report.js.map +1 -1
  54. package/dist/ui/capability-editor.js +268 -15
  55. package/dist/ui/profile-editor.js +271 -18
  56. package/dist/ui/swarm-dashboard.js +340 -51
  57. package/dist/ui/task-detail-view.js +69 -33
  58. package/dist/ui/trace-to-timeline.d.ts +2 -0
  59. package/dist/ui/trace-to-timeline.d.ts.map +1 -1
  60. package/dist/ui/trace-to-timeline.js.map +1 -1
  61. package/dist/ui/use-stream-timeline.d.ts +2 -0
  62. package/dist/ui/use-stream-timeline.d.ts.map +1 -1
  63. package/dist/ui/use-stream-timeline.js +76 -34
  64. package/dist/ui/use-stream-timeline.js.map +1 -1
  65. package/flowweaver.manifest.json +1 -1
  66. package/package.json +1 -1
  67. package/src/bot/assistant-tools.ts +5 -11
  68. package/src/bot/behavior-defaults.ts +12 -5
  69. package/src/bot/capability-registry.ts +300 -18
  70. package/src/bot/dashboard.ts +3 -3
  71. package/src/bot/hierarchy-event-log.ts +64 -0
  72. package/src/bot/operations.ts +7 -0
  73. package/src/bot/profile-store.ts +46 -0
  74. package/src/bot/runner.ts +51 -16
  75. package/src/bot/step-executor.ts +32 -1
  76. package/src/bot/swarm-controller.ts +67 -6
  77. package/src/bot/task-store.ts +22 -38
  78. package/src/bot/task-types.ts +7 -1
  79. package/src/bot/types.ts +4 -0
  80. package/src/node-types/bot-report.ts +63 -12
  81. package/src/node-types/build-context.ts +32 -0
  82. package/src/node-types/report.ts +60 -8
  83. package/src/ui/task-detail-view.tsx +3 -0
  84. package/src/ui/trace-to-timeline.ts +2 -0
  85. package/src/ui/use-stream-timeline.ts +81 -38
@@ -10,7 +10,7 @@ import type { CapabilityDefinition } from './capability-types.js';
10
10
  import {
11
11
  OP_WRITE_FILE, OP_READ_FILE, OP_PATCH_FILE, OP_LIST_FILES,
12
12
  OP_RUN_SHELL, OP_VALIDATE, OP_TSC_CHECK, OP_RUN_TESTS,
13
- OP_TASK_CREATE,
13
+ OP_TASK_CREATE, OP_REMEMBER, OP_RECALL,
14
14
  } from './operations.js';
15
15
 
16
16
  // ---------------------------------------------------------------------------
@@ -36,6 +36,92 @@ Do NOT describe what you would do — actually do it by calling tools.
36
36
  - Be concise — let tool results speak.`,
37
37
  };
38
38
 
39
+ // ---------------------------------------------------------------------------
40
+ // Role capabilities — define bot identity and primary directive
41
+ // ---------------------------------------------------------------------------
42
+
43
+ const CAP_ROLE_ORCHESTRATOR: CapabilityDefinition = {
44
+ name: 'role-orchestrator',
45
+ description: 'Orchestrator role: decomposes objectives into tasks, assigns profiles, creates project briefs.',
46
+ tools: [OP_TASK_CREATE, OP_LIST_FILES, OP_READ_FILE],
47
+ prompt: `## YOUR ROLE: Orchestrator
48
+ You DECOMPOSE and ASSIGN. You never write code or create files directly.
49
+
50
+ Your job:
51
+ 1. Analyze the objective and understand the project scope
52
+ 2. Create a PROJECT BRIEF (a concise description of what we're building, how pieces connect, conventions to follow)
53
+ 3. Break the objective into focused subtasks using task_create
54
+ 4. ALWAYS set assignedProfile on every subtask:
55
+ - Code writing, file creation → "developer"
56
+ - Code review, quality checks → "reviewer"
57
+ - Project setup, dependencies, config → "ops"
58
+ 5. Set dependencies so tasks execute in the right order
59
+ 6. Include the project brief in every subtask's description
60
+
61
+ You do NOT have write_file, patch_file, or run_shell. You cannot execute — only plan and delegate.
62
+
63
+ ### Project Brief Format
64
+ Include this at the TOP of every subtask description:
65
+ "PROJECT: [what we're building]. STRUCTURE: [file layout]. CONVENTIONS: [naming, patterns, exports]."
66
+
67
+ ### Subtask Quality
68
+ Each subtask must be:
69
+ - Focused (one file or one concern)
70
+ - Self-contained (has enough context to execute independently)
71
+ - Properly routed (assignedProfile is set)
72
+ - Ordered (dependsOn reflects real dependencies)`,
73
+ };
74
+
75
+ const CAP_ROLE_DEVELOPER: CapabilityDefinition = {
76
+ name: 'role-developer',
77
+ description: 'Developer role: writes code, creates files, runs commands. Executes directly, never decomposes.',
78
+ prompt: `## YOUR ROLE: Developer
79
+ You WRITE CODE. Execute the task directly using write_file, patch_file, and run_shell.
80
+
81
+ Your job:
82
+ 1. Read the task description (including the project brief)
83
+ 2. Create a plan with CONCRETE file operations (write_file, patch_file, run_shell)
84
+ 3. Execute every step — produce actual files on disk
85
+ 4. Verify your work compiles and is correct
86
+
87
+ You do NOT have task_create. You cannot create subtasks or delegate.
88
+ If the task seems too large, do your best — the orchestrator already decomposed it for you.
89
+
90
+ ### Output Requirements
91
+ Your plan MUST include at least one write_file, patch_file, or run_shell step.
92
+ A plan with only "respond" steps is a FAILURE — you must produce artifacts.`,
93
+ };
94
+
95
+ const CAP_ROLE_REVIEWER: CapabilityDefinition = {
96
+ name: 'role-reviewer',
97
+ description: 'Reviewer role: reads and evaluates code quality, security, correctness.',
98
+ prompt: `## YOUR ROLE: Reviewer
99
+ You READ and EVALUATE code. Check quality, security, correctness, and consistency.
100
+
101
+ Your job:
102
+ 1. Read the files that were created/modified
103
+ 2. Check against the task description and project conventions
104
+ 3. Report findings with file:line and severity
105
+ 4. Use patch_file to fix minor issues directly
106
+ 5. For major issues, document them clearly in your report
107
+
108
+ You do NOT have task_create or write_file. You can only read and patch.`,
109
+ };
110
+
111
+ const CAP_ROLE_OPS: CapabilityDefinition = {
112
+ name: 'role-ops',
113
+ description: 'Ops role: sets up project infrastructure, configs, dependencies.',
114
+ prompt: `## YOUR ROLE: Ops
115
+ You SET UP infrastructure — package.json, tsconfig.json, directory structure, dependencies.
116
+
117
+ Your job:
118
+ 1. Initialize project structure (create config files, directories)
119
+ 2. Install dependencies with run_shell
120
+ 3. Ensure the project builds and tests can run
121
+
122
+ You do NOT have task_create. You execute infrastructure tasks directly.`,
123
+ };
124
+
39
125
  const CAP_FILE_OPS: CapabilityDefinition = {
40
126
  name: 'file-ops',
41
127
  description: 'File read/write/patch operations and best practices for file manipulation.',
@@ -67,13 +153,31 @@ Use run_shell for running tests (npx vitest), validation (flow-weaver validate),
67
153
 
68
154
  const CAP_TASK_MGMT: CapabilityDefinition = {
69
155
  name: 'task-mgmt',
70
- description: 'Create and manage swarm subtasks for parallel execution.',
156
+ description: 'Create and manage swarm subtasks for parallel execution, with decomposition and review nudges.',
71
157
  tools: [OP_TASK_CREATE],
72
- prompt: `## Task Management
73
- - task_create: Create swarm subtasks for parallel execution. args: { title, description, complexity, subtasks[] }
74
- - task_list, task_get, task_update: Query and update existing tasks
75
-
76
- Use task_create to decompose complex work into smaller, independent subtasks that other bots can execute in parallel.`,
158
+ prompt: `## Task Management & Decomposition
159
+
160
+ - task_create: Create swarm subtasks. args: { title, description, complexity, subtasks[], dependsOn[], assignedProfile? }
161
+
162
+ ### Decomposition
163
+ When you encounter a broad objective (multi-file, multi-concern), decompose into subtasks:
164
+ - If the task is bigger than a single file change, create subtasks instead of doing it all yourself.
165
+ - Minimize dependencies between subtasks to maximize parallel execution.
166
+ - Set complexity per subtask: trivial | simple | moderate | complex.
167
+ - Use dependsOn to express blocking relationships (e.g., setup before code, code before tests).
168
+
169
+ ### Review Task Creation
170
+ After creating or modifying multiple files, create a review task:
171
+ - title: "Review: [what was changed]"
172
+ - description: List the files modified and what to check
173
+ - assignedProfile: "reviewer"
174
+ - complexity: "simple"
175
+ Skip review for trivial single-file tasks.
176
+
177
+ ### Dependency Guidelines
178
+ - BAD: A → B → C → D (serial, slow)
179
+ - GOOD: A → [B + C + D] (A blocks all, but B/C/D run in parallel)
180
+ Structure as: setup → independent implementations → integration/testing.`,
77
181
  };
78
182
 
79
183
  const CAP_FW_GRAMMAR: CapabilityDefinition = {
@@ -156,17 +260,41 @@ Note: compile, validate, modify, diff, diagram, and describe operations are avai
156
260
 
157
261
  const CAP_CODE_REVIEW: CapabilityDefinition = {
158
262
  name: 'code-review',
159
- description: 'Code review guidelines, quality checklist, and security review patterns.',
160
- prompt: `## Code Review
161
-
162
- When reviewing code, check for:
163
- 1. Correctness: Does the code do what the task asked?
164
- 2. Security: No hardcoded secrets, no injection vulnerabilities, no exposed APIs
165
- 3. Style: Consistent with project conventions, proper naming, no dead code
166
- 4. Testing: Are there tests? Do they cover edge cases?
167
- 5. Performance: No unnecessary loops, no blocking calls in async code
168
-
169
- Report concerns with specific file:line references and suggested fixes.`,
263
+ description: 'Comprehensive code review with correctness, security, style, testing, and performance checks.',
264
+ tools: [OP_READ_FILE, OP_PATCH_FILE, OP_RUN_SHELL],
265
+ prompt: `## Code Review Checklist
266
+
267
+ ### 1. Correctness
268
+ - Does the code do what the task asked?
269
+ - Edge cases handled (empty input, null, invalid types)?
270
+ - Error paths covered (try/catch, validation)?
271
+ - Return types match function signature?
272
+
273
+ ### 2. Security
274
+ - NO hardcoded API keys, passwords, or tokens (use env vars)
275
+ - NO shell: true in child_process (command injection risk)
276
+ - NO eval() or Function() with untrusted input
277
+ - User input validated and sanitized before use
278
+ - File paths validated (no ../ traversal)
279
+
280
+ ### 3. Style
281
+ - Naming is clear and consistent with project conventions
282
+ - No dead code (unused variables, unreachable branches)
283
+ - No debug statements left in (console.log, debugger)
284
+ - Imports organized, no duplicates
285
+
286
+ ### 4. Testing
287
+ - Unit tests exist for new/changed functions
288
+ - Tests cover happy path AND edge cases
289
+ - Error cases have tests
290
+ - Code coverage adequate (aim for 80%+ of changed code)
291
+
292
+ ### 5. Performance
293
+ - No O(n²) loops where O(n) is possible
294
+ - No blocking I/O in async code
295
+ - No memory leaks (listeners removed, timers cleared)
296
+
297
+ Report findings as: FILE:LINE | SEVERITY (critical/high/medium/low) | ISSUE → Fix suggestion`,
170
298
  };
171
299
 
172
300
  const CAP_WEB: CapabilityDefinition = {
@@ -186,6 +314,134 @@ Use list_files to understand the project structure before making changes.
186
314
  The context bundle (when available) provides a snapshot of the workspace.`,
187
315
  };
188
316
 
317
+ // ---------------------------------------------------------------------------
318
+ // New capabilities — swarm improvements
319
+ // ---------------------------------------------------------------------------
320
+
321
+ const CAP_VERIFICATION: CapabilityDefinition = {
322
+ name: 'verification',
323
+ description: 'Post-write verification: run tsc and tests to catch errors before delivery.',
324
+ tools: [OP_RUN_SHELL],
325
+ prompt: `## Verification
326
+
327
+ After writing or patching code, ALWAYS verify your work:
328
+ 1. Run \`npx tsc --noEmit\` in the project root to catch TypeScript errors
329
+ 2. If package.json has a "test" script, run \`npm test\` to validate functionality
330
+ 3. If verification fails, read the errors, fix the code, and re-verify
331
+
332
+ Include verification as explicit steps in your plan. Verification is NOT optional.
333
+ Do NOT deliver code that hasn't been verified.`,
334
+ };
335
+
336
+ const CAP_CROSS_FILE_CHECK: CapabilityDefinition = {
337
+ name: 'cross-file-check',
338
+ description: 'Verify imports, exports, module paths, and cross-file dependencies.',
339
+ tools: [OP_READ_FILE, OP_LIST_FILES, OP_RUN_SHELL],
340
+ prompt: `## Cross-File Dependency Checks
341
+
342
+ When modifying code that affects multiple files:
343
+ 1. If you rename an export, grep for all imports of it and update them
344
+ 2. Verify relative import paths resolve correctly (../types vs ./types)
345
+ 3. Check for circular dependencies (A imports B imports A)
346
+ 4. If you change a function signature, update all callers
347
+ 5. Use \`run_shell\` with grep to search: grep -r "functionName" src/
348
+
349
+ Do NOT move or rename exports without verifying all dependents.`,
350
+ };
351
+
352
+ const CAP_PROJECT_SETUP: CapabilityDefinition = {
353
+ name: 'project-setup',
354
+ description: 'Initialize new projects with correct structure, config, and dependencies.',
355
+ tools: [OP_WRITE_FILE, OP_RUN_SHELL],
356
+ prompt: `## Project Setup
357
+
358
+ When initializing a project:
359
+ 1. Create package.json with name, type: "module", main, scripts (build, test)
360
+ 2. Create tsconfig.json with strict: true, module: "esnext", target: "ES2020"
361
+ 3. Create standard directories: src/, tests/
362
+ 4. Install dependencies with run_shell: npm install <deps>
363
+ 5. Create .gitignore excluding node_modules/, dist/
364
+ 6. Verify setup: run tsc --noEmit to ensure TypeScript compiles`,
365
+ };
366
+
367
+ const CAP_SECURITY: CapabilityDefinition = {
368
+ name: 'security',
369
+ description: 'Audit code for vulnerabilities, secrets, and security best practices.',
370
+ tools: [OP_READ_FILE, OP_LIST_FILES, OP_RUN_SHELL],
371
+ prompt: `## Security Audit
372
+
373
+ Check for:
374
+ 1. **Secrets**: NO hardcoded API keys, passwords, tokens. Use env vars.
375
+ grep -r "password\\|secret\\|apiKey\\|token" src/ to find leaks.
376
+ 2. **Injection**: NO string concatenation in SQL. NO shell: true in child_process. NO eval().
377
+ 3. **Dependencies**: Run npm audit to check for known CVEs.
378
+ 4. **File paths**: Validate paths to prevent ../ traversal attacks.
379
+ 5. **Data handling**: Validate user input (type, length, format). Sanitize before logging.
380
+
381
+ Report findings with severity: critical | high | medium | low.`,
382
+ };
383
+
384
+ const CAP_DECOMPOSITION: CapabilityDefinition = {
385
+ name: 'decomposition',
386
+ description: 'Break complex objectives into subtask DAGs with dependencies for parallel execution.',
387
+ tools: [OP_TASK_CREATE],
388
+ prompt: `## Task Decomposition
389
+
390
+ When given a large objective, break it into smaller subtasks:
391
+ 1. Identify all work items (files, features, tests)
392
+ 2. Group by dependency: what must happen first?
393
+ 3. Create subtasks with task_create, each focused on one responsibility
394
+ 4. Set dependencies with dependsOn to model blocking relationships
395
+ 5. Minimize dependencies to maximize parallel execution
396
+ 6. Estimate complexity per subtask: trivial | simple | moderate | complex
397
+
398
+ Example: "Implement auth module"
399
+ - Task A: Extract shared auth types (simple)
400
+ - Task B: Rewrite login endpoint (moderate, depends on A)
401
+ - Task C: Add login tests (moderate, depends on B)
402
+ - Task D: Update auth docs (simple, independent — runs in parallel with B)
403
+
404
+ Assign profiles: code tasks → developer, review tasks → reviewer, infra → ops.`,
405
+ };
406
+
407
+ const CAP_ROUTING: CapabilityDefinition = {
408
+ name: 'routing',
409
+ description: 'Route tasks to appropriate bot profiles based on capabilities and complexity.',
410
+ tools: [OP_TASK_CREATE],
411
+ prompt: `## Task Routing
412
+
413
+ When creating subtasks, assign the right profile:
414
+ - Code writing, file creation, bug fixes → developer profile
415
+ - Code review, quality checks → reviewer profile
416
+ - Shell commands, project setup, infrastructure → ops profile
417
+ - Leave assignedProfile empty for auto-triage when unsure
418
+
419
+ Match complexity to profile capabilities:
420
+ - trivial/simple tasks: any profile (prefer cheapest)
421
+ - moderate tasks: specialist profiles
422
+ - complex tasks: profiles with full capability sets`,
423
+ };
424
+
425
+ const CAP_MEMORY: CapabilityDefinition = {
426
+ name: 'memory',
427
+ description: 'Remember and recall project conventions for continuity across sessions.',
428
+ tools: [OP_REMEMBER, OP_RECALL],
429
+ prompt: `## Project Memory
430
+
431
+ Persist project conventions for future sessions:
432
+ - remember: Save a convention. args: { key: "naming", value: "kebab-case for files" }
433
+ - recall: Load all saved conventions. args: {} — returns project memory.
434
+
435
+ What to remember:
436
+ - Naming conventions (file names, variable names)
437
+ - Architecture decisions (Result pattern, Zod for validation)
438
+ - Test patterns (where tests go, what framework)
439
+ - Common dependencies and their usage
440
+
441
+ Before planning, recall project memory to follow established patterns.
442
+ When you discover a new convention, remember it for future bots.`,
443
+ };
444
+
189
445
  // ---------------------------------------------------------------------------
190
446
  // Registry
191
447
  // ---------------------------------------------------------------------------
@@ -193,6 +449,12 @@ The context bundle (when available) provides a snapshot of the workspace.`,
193
449
  /** All built-in capability definitions. */
194
450
  export const BUILT_IN_CAPABILITIES: readonly CapabilityDefinition[] = [
195
451
  CAP_CORE,
452
+ // Role capabilities
453
+ CAP_ROLE_ORCHESTRATOR,
454
+ CAP_ROLE_DEVELOPER,
455
+ CAP_ROLE_REVIEWER,
456
+ CAP_ROLE_OPS,
457
+ // Tool capabilities
196
458
  CAP_FILE_OPS,
197
459
  CAP_SHELL,
198
460
  CAP_TASK_MGMT,
@@ -203,8 +465,28 @@ export const BUILT_IN_CAPABILITIES: readonly CapabilityDefinition[] = [
203
465
  CAP_CODE_REVIEW,
204
466
  CAP_WEB,
205
467
  CAP_CONTEXT,
468
+ // Swarm improvement capabilities
469
+ CAP_VERIFICATION,
470
+ CAP_CROSS_FILE_CHECK,
471
+ CAP_PROJECT_SETUP,
472
+ CAP_SECURITY,
473
+ CAP_DECOMPOSITION,
474
+ CAP_ROUTING,
475
+ CAP_MEMORY,
206
476
  ];
207
477
 
478
+ // ---------------------------------------------------------------------------
479
+ // Per-profile capability pools — defines what each role CAN use
480
+ // ---------------------------------------------------------------------------
481
+
482
+ /** Capability pools per profile role. Triage selects from these per task. */
483
+ export const PROFILE_CAPABILITIES: Record<string, string[]> = {
484
+ orchestrator: ['core', 'role-orchestrator', 'decomposition', 'routing', 'task-mgmt', 'context'],
485
+ developer: ['core', 'role-developer', 'file-ops', 'shell', 'verification', 'cross-file-check', 'fw-grammar', 'fw-validate', 'context'],
486
+ reviewer: ['core', 'role-reviewer', 'code-review', 'file-ops', 'security', 'context'],
487
+ ops: ['core', 'role-ops', 'file-ops', 'shell', 'project-setup', 'verification', 'context'],
488
+ };
489
+
208
490
  const capabilityMap = new Map<string, CapabilityDefinition>(
209
491
  BUILT_IN_CAPABILITIES.map(c => [c.name, c]),
210
492
  );
@@ -326,12 +326,12 @@ export class DashboardServer {
326
326
  const pending = tasks.filter(t => t.status === 'pending').length;
327
327
  const inProgress = tasks.filter(t => t.status === 'in-progress').length;
328
328
  const done = tasks.filter(t => t.status === 'done').length;
329
- const failed = tasks.filter(t => t.status === 'failed').length;
329
+ const cancelled = tasks.filter(t => t.status === 'cancelled').length;
330
330
  res.writeHead(200, { 'Content-Type': 'application/json' });
331
- res.end(JSON.stringify({ status: inProgress > 0 ? 'executing' : 'idle', pending, inProgress, done, failed }));
331
+ res.end(JSON.stringify({ status: inProgress > 0 ? 'executing' : 'idle', pending, inProgress, done, cancelled }));
332
332
  }).catch(() => {
333
333
  res.writeHead(200, { 'Content-Type': 'application/json' });
334
- res.end(JSON.stringify({ status: 'idle', pending: 0, inProgress: 0, done: 0, failed: 0 }));
334
+ res.end(JSON.stringify({ status: 'idle', pending: 0, inProgress: 0, done: 0, cancelled: 0 }));
335
335
  });
336
336
  }
337
337
 
@@ -0,0 +1,64 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+
4
+ export interface HierarchyEvent {
5
+ id: number;
6
+ parentId: string;
7
+ type: string;
8
+ taskId: string;
9
+ timestamp: number;
10
+ data?: Record<string, unknown>;
11
+ }
12
+
13
+ /**
14
+ * Append-only event log scoped to task hierarchies.
15
+ *
16
+ * Events are tagged with `parentId` so sibling tasks can read only
17
+ * events relevant to their hierarchy. Unrelated task hierarchies
18
+ * don't see each other's events.
19
+ *
20
+ * Writes to `.weaver/hierarchy-events.ndjson`.
21
+ */
22
+ export class HierarchyEventLog {
23
+ private readonly filePath: string;
24
+ private nextId = 0;
25
+
26
+ constructor(projectDir: string) {
27
+ const dir = path.join(projectDir, '.weaver');
28
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
29
+ this.filePath = path.join(dir, 'hierarchy-events.ndjson');
30
+ }
31
+
32
+ /** Append a hierarchy-scoped event. */
33
+ emit(event: { parentId: string; type: string; taskId: string; data?: Record<string, unknown> }): void {
34
+ const full: HierarchyEvent = { ...event, id: this.nextId++, timestamp: Date.now() };
35
+ fs.appendFileSync(this.filePath, JSON.stringify(full) + '\n', 'utf-8');
36
+ }
37
+
38
+ /**
39
+ * Read events for a specific parent hierarchy, starting from offset.
40
+ * Only returns events matching the given parentId.
41
+ */
42
+ tailByParent(parentId: string, offset = 0): HierarchyEvent[] {
43
+ if (!fs.existsSync(this.filePath)) return [];
44
+ const content = fs.readFileSync(this.filePath, 'utf-8');
45
+ const result: HierarchyEvent[] = [];
46
+ for (const line of content.split('\n')) {
47
+ const trimmed = line.trim();
48
+ if (!trimmed) continue;
49
+ try {
50
+ const event = JSON.parse(trimmed) as HierarchyEvent;
51
+ if (event.parentId === parentId && event.id >= offset) {
52
+ result.push(event);
53
+ }
54
+ } catch { /* skip corrupt line */ }
55
+ }
56
+ return result;
57
+ }
58
+
59
+ /** Remove all events. */
60
+ clear(): void {
61
+ try { fs.unlinkSync(this.filePath); } catch { /* ok */ }
62
+ this.nextId = 0;
63
+ }
64
+ }
@@ -34,6 +34,13 @@ export const OP_RUN_TESTS = 'run_tests';
34
34
 
35
35
  export const OP_TASK_CREATE = 'task_create';
36
36
 
37
+ // ---------------------------------------------------------------------------
38
+ // Memory
39
+ // ---------------------------------------------------------------------------
40
+
41
+ export const OP_REMEMBER = 'remember';
42
+ export const OP_RECALL = 'recall';
43
+
37
44
  // ---------------------------------------------------------------------------
38
45
  // Passthrough (no execution needed)
39
46
  // ---------------------------------------------------------------------------
@@ -3,6 +3,7 @@ import * as path from 'node:path';
3
3
  import * as crypto from 'node:crypto';
4
4
  import type { BotProfile, CreateProfileInput, Capability } from './profile-types.js';
5
5
  import { buildDefaultBehavior } from './behavior-defaults.js';
6
+ import { PROFILE_CAPABILITIES } from './capability-registry.js';
6
7
 
7
8
  // ---------------------------------------------------------------------------
8
9
  // Default profiles — enterprise-ready starting kit
@@ -152,6 +153,7 @@ const DEFAULT_PROFILES: Record<string, Array<Omit<CreateProfileInput, 'botId'>>>
152
153
  // Standard tier for plan+execute. 3 retries then block.
153
154
  // Iron Law: investigate before fixing → reportConcerns on.
154
155
  behavior: {
156
+ capabilities: PROFILE_CAPABILITIES.developer,
155
157
  phases: {
156
158
  plan: { enabled: true, tier: 'standard' as const },
157
159
  execute: { enabled: true, tier: 'standard' as const },
@@ -185,6 +187,7 @@ const DEFAULT_PROFILES: Record<string, Array<Omit<CreateProfileInput, 'botId'>>>
185
187
  // Finding classification: AUTO-FIX / ASK / INFORM → requireEvidence.
186
188
  // Low retries — if review fails twice, escalate to human.
187
189
  behavior: {
190
+ capabilities: PROFILE_CAPABILITIES.reviewer,
188
191
  phases: {
189
192
  plan: { enabled: true, tier: 'fast' as const },
190
193
  execute: { enabled: false, tier: 'standard' as const },
@@ -217,6 +220,7 @@ const DEFAULT_PROFILES: Record<string, Array<Omit<CreateProfileInput, 'botId'>>>
217
220
  // Blocked from src/ and lib/ — ops touches config, scripts, CI only.
218
221
  // Reassign on exhaustion — don't block, escalate to human.
219
222
  behavior: {
223
+ capabilities: PROFILE_CAPABILITIES.ops,
220
224
  phases: {
221
225
  plan: { enabled: true, tier: 'standard' as const },
222
226
  execute: { enabled: true, tier: 'standard' as const },
@@ -230,6 +234,48 @@ const DEFAULT_PROFILES: Record<string, Array<Omit<CreateProfileInput, 'botId'>>>
230
234
  },
231
235
  },
232
236
  },
237
+ {
238
+ name: 'Orchestrator',
239
+ description: 'Decomposes high-level objectives into tasks, assigns profiles, manages dependencies.',
240
+ icon: 'accountTree',
241
+ color: 'color-node-purple-icon',
242
+ capabilities: [
243
+ { name: 'decomposition', description: 'Break complex objectives into subtask DAGs with dependencies' },
244
+ { name: 'routing', description: 'Match tasks to the right bot profile based on capabilities' },
245
+ { name: 'task-mgmt', description: 'Create, prioritize, and manage swarm tasks' },
246
+ ],
247
+ preferences: {
248
+ costStrategy: 'frugal',
249
+ requireApproval: false,
250
+ instructions: `You are the orchestrator. Your job is to decompose high-level objectives into concrete, actionable subtasks that other bots can execute.
251
+
252
+ ## Protocol
253
+ 1. ANALYZE: Understand the objective. What files, features, and concerns are involved?
254
+ 2. DECOMPOSE: Break into subtasks. Each subtask should be completable by a single bot.
255
+ 3. ASSIGN: Set assignedProfile per task (developer, reviewer, ops). Set complexity and priority.
256
+ 4. DEPENDENCIES: Use dependsOn to model blocking relationships. Minimize deps for parallelism.
257
+
258
+ ## Rules
259
+ - You do NOT write code yourself. You create tasks for other bots.
260
+ - CRITICAL: Every subtask MUST have assignedProfile set to "developer", "reviewer", or "ops". NEVER leave it empty or set it to "orchestrator".
261
+ - Every subtask needs: title, description, assignedProfile, complexity.
262
+ - Code/file tasks → assignedProfile: "developer". Setup/infra → assignedProfile: "ops". Review → assignedProfile: "reviewer".
263
+ - Structure as: setup → independent implementations → integration → review.
264
+ - If a task is simple enough (single file, clear scope), don't decompose further.`,
265
+ behavior: {
266
+ capabilities: PROFILE_CAPABILITIES.orchestrator,
267
+ phases: {
268
+ plan: { enabled: true, tier: 'fast' as const },
269
+ execute: { enabled: true, tier: 'fast' as const },
270
+ review: { enabled: false },
271
+ validate: { enabled: false },
272
+ gitOps: { enabled: false },
273
+ },
274
+ escalation: { maxAttempts: 2, onExhausted: 'block' as const },
275
+ exitProtocol: { reportConcerns: false, requireEvidence: false },
276
+ },
277
+ },
278
+ },
233
279
  ],
234
280
  'weaver-genesis': [
235
281
  {
package/src/bot/runner.ts CHANGED
@@ -289,10 +289,6 @@ export async function runWorkflow(
289
289
  const nodeStartTimes = new Map<string, number>();
290
290
  const nodeTypes = new Map<string, string>(); // nodeId → nodeTypeName
291
291
  const nodeOutputs = new Map<string, Array<{ portLabel: string; value: unknown }>>();
292
- // Dedup: the FW runtime can emit duplicate STATUS_CHANGED events per node
293
- // (from both the expression evaluator and the graph engine). Track which
294
- // node-start/node-complete events we've already emitted to avoid duplicates.
295
- const emittedNodeEvents = new Set<string>(); // "nodeId:eventType"
296
292
 
297
293
  /** Try to parse JSON strings into objects so the UI renders them as structured JSON. */
298
294
  function resolveOutputValue(value: unknown): unknown {
@@ -358,17 +354,6 @@ export async function runWorkflow(
358
354
  }
359
355
 
360
356
  if (eventType) {
361
- // Deduplicate: skip if we already emitted this event for this node
362
- const dedupKey = `${nodeId}:${eventType}`;
363
- if (emittedNodeEvents.has(dedupKey)) return;
364
- emittedNodeEvents.add(dedupKey);
365
- // Clear dedup tracking for the node when it completes/errors so it can
366
- // re-enter the pipeline (e.g. in retry loops or multi-execution workflows)
367
- if (eventType !== 'node-start') {
368
- emittedNodeEvents.delete(`${nodeId}:node-start`);
369
- emittedNodeEvents.delete(dedupKey);
370
- }
371
-
372
357
  // Attach accumulated outputs on completion/error, then clear
373
358
  const outputs = nodeOutputs.get(nodeId);
374
359
  if (eventType !== 'node-start') nodeOutputs.delete(nodeId);
@@ -454,6 +439,54 @@ export async function runWorkflow(
454
439
  }
455
440
  } catch { /* extraction is best-effort */ }
456
441
 
442
+ // Build markdown report from the extracted context data
443
+ let report: string | undefined;
444
+ try {
445
+ const ctxStr = result?.ctx as string | undefined;
446
+ if (ctxStr) {
447
+ const ctx = JSON.parse(ctxStr);
448
+ const md: string[] = [];
449
+ md.push(`## ${success ? 'Task Completed' : 'Task Failed'}`);
450
+ md.push('');
451
+
452
+ // Steps
453
+ if (stepLog && stepLog.length > 0) {
454
+ md.push('### Steps');
455
+ md.push('');
456
+ for (const s of stepLog) {
457
+ const icon = s.status === 'ok' ? '**ok**' : s.status === 'error' ? '**error**' : '**blocked**';
458
+ md.push(`- ${s.step} (${icon})${s.detail ? `: ${s.detail}` : ''}`);
459
+ }
460
+ md.push('');
461
+ }
462
+
463
+ // Files
464
+ const files: string[] = ctx.filesModified ? JSON.parse(ctx.filesModified) : [];
465
+ if (files.length > 0) {
466
+ md.push('### Files Modified');
467
+ md.push('');
468
+ for (const f of files) md.push(`- \`${f}\``);
469
+ md.push('');
470
+ }
471
+
472
+ // Review
473
+ if (ctx.reviewJson) {
474
+ const review = JSON.parse(ctx.reviewJson) as Record<string, string>;
475
+ if (review.intent || review.execution || review.result || review.completeness) {
476
+ md.push('### Review');
477
+ md.push('');
478
+ for (const key of ['intent', 'execution', 'result', 'completeness']) {
479
+ if (review[key]) md.push(`- **${key}:** ${review[key]}`);
480
+ }
481
+ if (review.reason) md.push(`\n${review.reason}`);
482
+ md.push('');
483
+ }
484
+ }
485
+
486
+ if (md.length > 2) report = md.join('\n');
487
+ }
488
+ } catch { /* report generation is best-effort */ }
489
+
457
490
  await notifier({
458
491
  type: 'workflow-complete',
459
492
  workflowFile: absPath,
@@ -466,6 +499,7 @@ export async function runWorkflow(
466
499
  persistCost(costSummary, absPath, providerConfig.name, verbose);
467
500
  recordRun(store, {
468
501
  id: runId, workflowFile: absPath, startedAt, success, outcome: outcome as RunOutcome, summary,
502
+ report,
469
503
  functionName: execResult.functionName, executionTime: execResult.executionTime,
470
504
  dryRun: false, provider: providerConfig.name, params: options?.params, stepLog,
471
505
  trace: collectedTrace.length > 0 ? collectedTrace : undefined,
@@ -477,13 +511,14 @@ export async function runWorkflow(
477
511
  botId: options?.botId,
478
512
  }, verbose);
479
513
 
480
- logEvent?.({ type: 'bot-completed', timestamp: Date.now(), data: { success, outcome, summary } });
514
+ logEvent?.({ type: 'bot-completed', timestamp: Date.now(), data: { success, outcome, summary, report } });
481
515
 
482
516
  auditEmit('run-complete', { success, outcome, summary });
483
517
 
484
518
  return {
485
519
  success,
486
520
  summary,
521
+ report,
487
522
  outcome,
488
523
  functionName: execResult.functionName,
489
524
  executionTime: execResult.executionTime,