@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.
- package/dist/bot/assistant-tools.d.ts.map +1 -1
- package/dist/bot/assistant-tools.js +5 -11
- package/dist/bot/assistant-tools.js.map +1 -1
- package/dist/bot/behavior-defaults.d.ts +2 -2
- package/dist/bot/behavior-defaults.d.ts.map +1 -1
- package/dist/bot/behavior-defaults.js +11 -6
- package/dist/bot/behavior-defaults.js.map +1 -1
- package/dist/bot/capability-registry.d.ts +2 -0
- package/dist/bot/capability-registry.d.ts.map +1 -1
- package/dist/bot/capability-registry.js +282 -15
- package/dist/bot/capability-registry.js.map +1 -1
- package/dist/bot/dashboard.js +3 -3
- package/dist/bot/dashboard.js.map +1 -1
- package/dist/bot/hierarchy-event-log.d.ts +37 -0
- package/dist/bot/hierarchy-event-log.d.ts.map +1 -0
- package/dist/bot/hierarchy-event-log.js +58 -0
- package/dist/bot/hierarchy-event-log.js.map +1 -0
- package/dist/bot/operations.d.ts +2 -0
- package/dist/bot/operations.d.ts.map +1 -1
- package/dist/bot/operations.js +5 -0
- package/dist/bot/operations.js.map +1 -1
- package/dist/bot/profile-store.d.ts.map +1 -1
- package/dist/bot/profile-store.js +46 -0
- package/dist/bot/profile-store.js.map +1 -1
- package/dist/bot/runner.d.ts.map +1 -1
- package/dist/bot/runner.js +51 -16
- package/dist/bot/runner.js.map +1 -1
- package/dist/bot/step-executor.d.ts.map +1 -1
- package/dist/bot/step-executor.js +36 -1
- package/dist/bot/step-executor.js.map +1 -1
- package/dist/bot/swarm-controller.d.ts +1 -0
- package/dist/bot/swarm-controller.d.ts.map +1 -1
- package/dist/bot/swarm-controller.js +64 -6
- package/dist/bot/swarm-controller.js.map +1 -1
- package/dist/bot/task-store.d.ts +1 -1
- package/dist/bot/task-store.d.ts.map +1 -1
- package/dist/bot/task-store.js +21 -36
- package/dist/bot/task-store.js.map +1 -1
- package/dist/bot/task-types.d.ts +5 -1
- package/dist/bot/task-types.d.ts.map +1 -1
- package/dist/bot/types.d.ts +4 -0
- package/dist/bot/types.d.ts.map +1 -1
- package/dist/node-types/bot-report.d.ts +3 -1
- package/dist/node-types/bot-report.d.ts.map +1 -1
- package/dist/node-types/bot-report.js +62 -11
- package/dist/node-types/bot-report.js.map +1 -1
- package/dist/node-types/build-context.d.ts.map +1 -1
- package/dist/node-types/build-context.js +32 -0
- package/dist/node-types/build-context.js.map +1 -1
- package/dist/node-types/report.d.ts +2 -0
- package/dist/node-types/report.d.ts.map +1 -1
- package/dist/node-types/report.js +61 -7
- package/dist/node-types/report.js.map +1 -1
- package/dist/ui/capability-editor.js +268 -15
- package/dist/ui/profile-editor.js +271 -18
- package/dist/ui/swarm-dashboard.js +340 -51
- package/dist/ui/task-detail-view.js +69 -33
- package/dist/ui/trace-to-timeline.d.ts +2 -0
- package/dist/ui/trace-to-timeline.d.ts.map +1 -1
- package/dist/ui/trace-to-timeline.js.map +1 -1
- package/dist/ui/use-stream-timeline.d.ts +2 -0
- package/dist/ui/use-stream-timeline.d.ts.map +1 -1
- package/dist/ui/use-stream-timeline.js +76 -34
- package/dist/ui/use-stream-timeline.js.map +1 -1
- package/flowweaver.manifest.json +1 -1
- package/package.json +1 -1
- package/src/bot/assistant-tools.ts +5 -11
- package/src/bot/behavior-defaults.ts +12 -5
- package/src/bot/capability-registry.ts +300 -18
- package/src/bot/dashboard.ts +3 -3
- package/src/bot/hierarchy-event-log.ts +64 -0
- package/src/bot/operations.ts +7 -0
- package/src/bot/profile-store.ts +46 -0
- package/src/bot/runner.ts +51 -16
- package/src/bot/step-executor.ts +32 -1
- package/src/bot/swarm-controller.ts +67 -6
- package/src/bot/task-store.ts +22 -38
- package/src/bot/task-types.ts +7 -1
- package/src/bot/types.ts +4 -0
- package/src/node-types/bot-report.ts +63 -12
- package/src/node-types/build-context.ts +32 -0
- package/src/node-types/report.ts +60 -8
- package/src/ui/task-detail-view.tsx +3 -0
- package/src/ui/trace-to-timeline.ts +2 -0
- 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
|
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
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: '
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
1. Correctness
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
);
|
package/src/bot/dashboard.ts
CHANGED
|
@@ -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
|
|
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,
|
|
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,
|
|
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
|
+
}
|
package/src/bot/operations.ts
CHANGED
|
@@ -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
|
// ---------------------------------------------------------------------------
|
package/src/bot/profile-store.ts
CHANGED
|
@@ -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,
|