brainclaw 1.5.5 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +5 -4
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli.js +124 -7
  4. package/dist/commands/bootstrap-loop.js +206 -0
  5. package/dist/commands/loop.js +156 -0
  6. package/dist/commands/loops-handlers.js +110 -55
  7. package/dist/commands/mcp-read-handlers.js +37 -0
  8. package/dist/commands/mcp-schemas.generated.js +33 -0
  9. package/dist/commands/mcp.js +661 -207
  10. package/dist/commands/questions.js +180 -0
  11. package/dist/commands/reply.js +190 -0
  12. package/dist/commands/session-end.js +105 -3
  13. package/dist/commands/session-start.js +32 -53
  14. package/dist/commands/setup.js +64 -13
  15. package/dist/commands/switch.js +17 -1
  16. package/dist/core/agent-capability.js +19 -0
  17. package/dist/core/agent-files.js +86 -0
  18. package/dist/core/agent-integrations.js +34 -0
  19. package/dist/core/agent-inventory.js +27 -0
  20. package/dist/core/agentrun-reconciler.js +130 -0
  21. package/dist/core/ai-agent-detection.js +17 -1
  22. package/dist/core/claims.js +54 -3
  23. package/dist/core/dirty-scope.js +242 -0
  24. package/dist/core/dispatch-status.js +219 -0
  25. package/dist/core/entity-operations.js +128 -9
  26. package/dist/core/execution-adapters.js +38 -2
  27. package/dist/core/facade-schema.js +71 -0
  28. package/dist/core/federation-cloud.js +27 -12
  29. package/dist/core/federation-materialize.js +57 -0
  30. package/dist/core/instruction-templates.js +2 -0
  31. package/dist/core/loops/bootstrap-acquire.js +195 -0
  32. package/dist/core/loops/facade-schema.js +68 -1
  33. package/dist/core/loops/hooks/bootstrap-write.js +144 -0
  34. package/dist/core/loops/hooks/notify-operator.js +148 -0
  35. package/dist/core/loops/hooks/survey-source-reader.js +256 -0
  36. package/dist/core/loops/index.js +8 -2
  37. package/dist/core/loops/next-expected.js +63 -0
  38. package/dist/core/loops/presets/bootstrap.js +75 -0
  39. package/dist/core/loops/presets/index.js +16 -0
  40. package/dist/core/loops/store.js +224 -4
  41. package/dist/core/loops/types.js +346 -1
  42. package/dist/core/loops/verbs.js +739 -6
  43. package/dist/core/schema.js +30 -2
  44. package/dist/core/state.js +62 -0
  45. package/dist/core/worktree.js +58 -0
  46. package/dist/facts.js +360 -5
  47. package/dist/facts.json +359 -4
  48. package/docs/cli.md +10 -7
  49. package/docs/concepts/dispatch-lifecycle.md +228 -0
  50. package/docs/concepts/loop-engine.md +55 -0
  51. package/docs/concepts/multi-agent-workflows.md +167 -166
  52. package/docs/concepts/troubleshooting.md +36 -2
  53. package/docs/index.md +4 -3
  54. package/docs/integrations/hermes.md +78 -0
  55. package/docs/integrations/overview.md +22 -18
  56. package/docs/mcp-schema-changelog.md +8 -1
  57. package/docs/quickstart-existing-project.md +1 -1
  58. package/package.json +5 -4
@@ -232,6 +232,17 @@ export const HandoffSchema = z.object({
232
232
  */
233
233
  superseded_by: z.string().optional(),
234
234
  supersedes: z.string().optional(),
235
+ /**
236
+ * pln#365 finalization: opt-in cloud federation. Optional (no default) so
237
+ * existing on-disk handoffs without the field continue to parse, AND so
238
+ * an unset value means "stay local" rather than "implicitly shared". To
239
+ * opt a handoff into cloud push, set `visibility: 'shared'` explicitly
240
+ * when building it. Session-end push uses literal `visibility === 'shared'`
241
+ * (cf. session-end.ts:isExplicitlyShared). Risk it mitigates: a session
242
+ * handoff with `snapshot.diff` carrying secrets would otherwise leak the
243
+ * moment cloud_sync flips on, by virtue of being created at all.
244
+ */
245
+ visibility: MemoryVisibilitySchema.optional(),
235
246
  });
236
247
  export const PlanStatusSchema = z.enum(['todo', 'in_progress', 'blocked', 'done', 'dropped']);
237
248
  export const PlanStepStatusSchema = z.enum(['todo', 'in_progress', 'testing', 'done', 'blocked']);
@@ -243,7 +254,8 @@ export const PlanStepSchema = z.object({
243
254
  created_at: z.string(),
244
255
  updated_at: z.string(),
245
256
  });
246
- export const PlanTypeSchema = z.enum(['feat', 'fix', 'chore', 'spike', 'doc']).default('feat');
257
+ export const PlanTypeEnumSchema = z.enum(['feat', 'fix', 'chore', 'spike', 'doc']);
258
+ export const PlanTypeSchema = PlanTypeEnumSchema.default('feat');
247
259
  export const PlanItemSchema = z.object({
248
260
  schema_version: z.number().int().positive().optional(),
249
261
  id: z.string(),
@@ -532,6 +544,13 @@ export const CandidateSchema = z.preprocess(candidatePreprocess, z.object({
532
544
  resolved_by: z.string().optional(),
533
545
  resolution_reason: z.string().optional(),
534
546
  provenance: ProvenancePassthroughSchema,
547
+ /**
548
+ * pln#365 finalization: opt-in cloud federation. Mirrors HandoffSchema —
549
+ * optional (no default) so unset means "stay local" and an agent must
550
+ * explicitly set `visibility: 'shared'` to opt a candidate into cloud
551
+ * push. Conservative because candidate.text can carry secrets.
552
+ */
553
+ visibility: MemoryVisibilitySchema.optional(),
535
554
  }));
536
555
  export const ReflectiveMemoryConfigSchema = z.object({
537
556
  enabled: z.boolean().default(true),
@@ -756,6 +775,7 @@ export const ActionRequiredSchema = z.object({
756
775
  tags: TagsWithDefaultSchema,
757
776
  });
758
777
  // --- Runtime notes schemas ---
778
+ export const RuntimeNoteTypeSchema = z.enum(['observation', 'session_start', 'session_end']);
759
779
  export const RuntimeNoteSchema = z.object({
760
780
  schema_version: z.number().int().positive().optional(),
761
781
  id: z.string(),
@@ -771,7 +791,7 @@ export const RuntimeNoteSchema = z.object({
771
791
  visibility: MemoryVisibilitySchema.default('shared'),
772
792
  host_id: z.string().optional(),
773
793
  expires_at: z.string().optional(),
774
- note_type: z.enum(['observation', 'session_start', 'session_end']).default('observation'),
794
+ note_type: RuntimeNoteTypeSchema.default('observation'),
775
795
  model: z.string().optional(),
776
796
  provenance: ProvenancePassthroughSchema,
777
797
  });
@@ -937,6 +957,11 @@ export const RemoteSyncSchema = z.object({
937
957
  ssh_key_path: z.string().optional(),
938
958
  sync_strategy: z.enum(['pull-only', 'push-pull', 'pr-based']).default('push-pull'),
939
959
  });
960
+ export const CloudSyncConfigSchema = z.object({
961
+ enabled: z.boolean().default(false),
962
+ endpoint: z.string().default('https://app.brainclaw.dev'),
963
+ api_key: z.string().optional(),
964
+ });
940
965
  export const SessionSnapshotSchema = z.object({
941
966
  schema_version: z.number().int().positive().optional(),
942
967
  session_id: z.string(),
@@ -1141,6 +1166,8 @@ export const AgentIntegrationNameSchema = z.enum([
1141
1166
  'continue',
1142
1167
  'roo',
1143
1168
  'kilocode',
1169
+ 'mistral-vibe',
1170
+ 'hermes',
1144
1171
  'openclaw',
1145
1172
  'nanoclaw',
1146
1173
  'nemoclaw',
@@ -1232,6 +1259,7 @@ export const ConfigSchema = z.object({
1232
1259
  target_audience: z.enum(['human', 'agent']).optional().default('human'),
1233
1260
  openclaw_bridge: z.boolean().optional().default(false),
1234
1261
  remote_sync: RemoteSyncSchema.optional(),
1262
+ cloud_sync: CloudSyncConfigSchema.optional(),
1235
1263
  telemetry: z.literal(false),
1236
1264
  allow_network: z.literal(false),
1237
1265
  redaction: RedactionConfigSchema,
@@ -37,6 +37,68 @@ function loadDirectoryItems(dirPath, schema, documentType) {
37
37
  }
38
38
  return items;
39
39
  }
40
+ const ENTITY_LOAD_CONFIG = {
41
+ constraint: { subdir: 'constraints', documentType: 'constraint', recursive: false },
42
+ decision: { subdir: 'decisions', documentType: 'decision', recursive: false },
43
+ trap: { subdir: 'traps', documentType: 'trap', recursive: false },
44
+ handoff: { subdir: 'handoffs', documentType: 'handoff', recursive: false },
45
+ plan: { subdir: 'plans', documentType: 'plan', recursive: false },
46
+ candidate: { subdir: 'inbox', documentType: 'candidate', recursive: false },
47
+ claim: { subdir: 'claims', documentType: 'claim', recursive: false },
48
+ assignment: { subdir: 'assignments', documentType: 'assignment', recursive: false },
49
+ agent_run: { subdir: 'runs', documentType: 'agent_run', recursive: false },
50
+ action: { subdir: 'actions', documentType: 'action_required', recursive: false },
51
+ runtime_note: { subdir: 'runtime', documentType: 'runtime_note', recursive: true },
52
+ };
53
+ function listJsonFiles(dirPath, recursive) {
54
+ if (!fs.existsSync(dirPath))
55
+ return [];
56
+ const files = [];
57
+ for (const entry of fs.readdirSync(dirPath).sort()) {
58
+ const fullPath = path.join(dirPath, entry);
59
+ const stat = fs.statSync(fullPath);
60
+ if (stat.isDirectory()) {
61
+ if (recursive)
62
+ files.push(...listJsonFiles(fullPath, true));
63
+ continue;
64
+ }
65
+ if (entry.endsWith('.json'))
66
+ files.push(fullPath);
67
+ }
68
+ return files;
69
+ }
70
+ function validationErrorsFrom(error) {
71
+ if (error && typeof error === 'object' && 'issues' in error && Array.isArray(error.issues)) {
72
+ return (error.issues).map((issue) => {
73
+ const issuePath = Array.isArray(issue.path) && issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
74
+ return `${issuePath}${issue.message ?? 'validation failed'}`;
75
+ });
76
+ }
77
+ return [error instanceof Error ? error.message : String(error)];
78
+ }
79
+ export function collectLoadValidationWarnings(entity, cwd) {
80
+ const config = ENTITY_LOAD_CONFIG[entity];
81
+ if (!config)
82
+ return [];
83
+ const effectiveCwd = cwd ?? process.cwd();
84
+ const dirPath = resolveEntityDir(config.subdir, effectiveCwd, 'read');
85
+ return listJsonFiles(dirPath, config.recursive).flatMap((filepath) => {
86
+ try {
87
+ loadVersionedJsonFile(config.documentType, filepath);
88
+ return [];
89
+ }
90
+ catch (error) {
91
+ return [{
92
+ entity_id: path.basename(filepath, '.json'),
93
+ validation_errors: validationErrorsFrom(error),
94
+ path: filepath,
95
+ }];
96
+ }
97
+ });
98
+ }
99
+ export function findLoadValidationWarning(entity, id, cwd) {
100
+ return collectLoadValidationWarnings(entity, cwd).find((warning) => warning.entity_id === id);
101
+ }
40
102
  export function loadState(cwd) {
41
103
  // Load from entity-aligned directories (with legacy fallback)
42
104
  const effectiveCwd = cwd ?? process.cwd();
@@ -94,6 +94,64 @@ export function hasGitLock(cwd) {
94
94
  const lockPath = path.join(gitDir.stdout.trim(), 'index.lock');
95
95
  return fs.existsSync(lockPath);
96
96
  }
97
+ /**
98
+ * Re-points an EXISTING worktree to `ref` via a hard reset of its checked-out
99
+ * branch + working tree. Used when a dispatch reuses an existing claim/worktree
100
+ * but pins a base ref: the worktree must reflect that ref, not stale state,
101
+ * otherwise the dirty-guard ref bypass would let the worker run on stale code
102
+ * (pln#520 Tier 2 / codex r2). Returns ok=false (with stderr) rather than
103
+ * throwing, so callers surface a visible warning instead of a hard failure.
104
+ */
105
+ export function resetWorktreeToRef(worktreePath, ref) {
106
+ if (!fs.existsSync(worktreePath)) {
107
+ return { ok: false, stderr: `worktree path does not exist: ${worktreePath}` };
108
+ }
109
+ if (hasGitLock(worktreePath)) {
110
+ return { ok: false, stderr: 'git index.lock present — another git operation is in progress' };
111
+ }
112
+ const res = runGit(['reset', '--hard', ref], worktreePath);
113
+ if (!res.ok) {
114
+ return { ok: false, stderr: res.stderr };
115
+ }
116
+ // `reset --hard` realigns HEAD + tracked files, but leaves UNTRACKED residue
117
+ // from a prior use of the worktree — files the worker could still compile or
118
+ // test against even though they don't exist at the pinned ref (codex r3).
119
+ // We do NOT auto-delete (a blind `git clean` would also remove the brainclaw
120
+ // sidecar and gitignored shared symlinks); instead we detect non-system
121
+ // untracked files and report them so the caller surfaces a visible warning
122
+ // rather than letting the stale state pass silently. Ignored files (e.g.
123
+ // node_modules) are not listed by --untracked-files=normal, so the symlinked
124
+ // shared paths are unaffected.
125
+ const status = runGit(['status', '--porcelain=v1', '-z', '--untracked-files=normal'], worktreePath);
126
+ if (!status.ok) {
127
+ // The reset succeeded but we cannot confirm the worktree is residue-free -
128
+ // surface it rather than silently reporting a clean reset (cardinal rule).
129
+ return {
130
+ ok: false,
131
+ stderr: `reset to ${ref} succeeded but the untracked-residue check (git status) failed: ${status.stderr.trim()}`,
132
+ };
133
+ }
134
+ if (status.stdout.length > 0) {
135
+ const residue = status.stdout
136
+ .split('\0')
137
+ .filter((entry) => entry.startsWith('?? '))
138
+ .map((entry) => entry.slice(3))
139
+ .filter((p) => {
140
+ const norm = p.replace(/\\/g, '/');
141
+ return norm !== '.brainclaw-worktree.json'
142
+ && !norm.startsWith('.brainclaw/')
143
+ && !norm.startsWith('.git/');
144
+ });
145
+ if (residue.length > 0) {
146
+ const sample = residue.slice(0, 5).join(', ');
147
+ return {
148
+ ok: false,
149
+ stderr: `reset to ${ref} succeeded but ${residue.length} untracked file(s) remain from prior worktree use (e.g. ${sample}) — the worker may see state absent at the ref. Remove them or dispatch with a fresh scope.`,
150
+ };
151
+ }
152
+ }
153
+ return { ok: true, stderr: '' };
154
+ }
97
155
  /**
98
156
  * Detects whether multiple distinct brainclaw sessions are using the same
99
157
  * physical worktree directory (shared-checkout risk).
package/dist/facts.js CHANGED
@@ -1,11 +1,11 @@
1
1
  // Generated by scripts/emit-site-facts.mjs at build time. Do not edit manually.
2
- // Source: brainclaw v1.5.5 on 2026-05-13T19:24:16.549Z
2
+ // Source: brainclaw v1.7.0 on 2026-05-28T00:12:31.140Z
3
3
  export const FACTS = {
4
- "version": "1.5.5",
5
- "generated_at": "2026-05-13T19:24:16.549Z",
4
+ "version": "1.7.0",
5
+ "generated_at": "2026-05-28T00:12:31.140Z",
6
6
  "tools": {
7
- "count": 60,
8
- "published_count": 59,
7
+ "count": 62,
8
+ "published_count": 61,
9
9
  "names": [
10
10
  "bclaw_bootstrap",
11
11
  "bclaw_release_notes",
@@ -30,10 +30,12 @@ export const FACTS = {
30
30
  "bclaw_check_security",
31
31
  "bclaw_read_inbox",
32
32
  "bclaw_get_thread",
33
+ "bclaw_dispatch_status",
33
34
  "bclaw_dispatch",
34
35
  "bclaw_send_message",
35
36
  "bclaw_ack_message",
36
37
  "bclaw_setup",
38
+ "bclaw_init_project",
37
39
  "bclaw_write_note",
38
40
  "bclaw_quick_capture",
39
41
  "bclaw_claim",
@@ -109,6 +111,359 @@ export const FACTS = {
109
111
  "action": "act",
110
112
  "cross_project_link": "xpl"
111
113
  }
114
+ },
115
+ "agent_integrations": {
116
+ "count": 19,
117
+ "names": [
118
+ "antigravity",
119
+ "claude-code",
120
+ "claude-sonnet",
121
+ "cline",
122
+ "codex",
123
+ "continue",
124
+ "cursor",
125
+ "github-copilot",
126
+ "hermes",
127
+ "kilocode",
128
+ "mistral-vibe",
129
+ "nanoclaw",
130
+ "nemoclaw",
131
+ "openclaw",
132
+ "opencode",
133
+ "picoclaw",
134
+ "roo",
135
+ "windsurf",
136
+ "zeroclaw"
137
+ ],
138
+ "profiles": [
139
+ {
140
+ "name": "antigravity",
141
+ "category": "code-agent",
142
+ "workflow_model": "interactive",
143
+ "tier": "B",
144
+ "has_mcp": true,
145
+ "has_hooks": false,
146
+ "has_skills": false,
147
+ "has_rules": true,
148
+ "instruction_file": "GEMINI.md",
149
+ "mcp_config_scope": "machine",
150
+ "role_capabilities": [
151
+ "execute",
152
+ "consult"
153
+ ],
154
+ "max_concurrent_tasks": 2
155
+ },
156
+ {
157
+ "name": "claude-code",
158
+ "category": "code-agent",
159
+ "workflow_model": "interactive",
160
+ "tier": "A",
161
+ "has_mcp": true,
162
+ "has_hooks": true,
163
+ "has_skills": true,
164
+ "has_rules": true,
165
+ "instruction_file": "CLAUDE.md",
166
+ "mcp_config_scope": "both",
167
+ "role_capabilities": [
168
+ "execute",
169
+ "coordinate",
170
+ "review",
171
+ "consult"
172
+ ],
173
+ "max_concurrent_tasks": 3
174
+ },
175
+ {
176
+ "name": "claude-sonnet",
177
+ "category": "code-agent",
178
+ "workflow_model": "interactive",
179
+ "tier": "A",
180
+ "has_mcp": true,
181
+ "has_hooks": true,
182
+ "has_skills": true,
183
+ "has_rules": true,
184
+ "instruction_file": "CLAUDE.md",
185
+ "mcp_config_scope": "both",
186
+ "role_capabilities": [
187
+ "execute",
188
+ "coordinate",
189
+ "review",
190
+ "consult"
191
+ ],
192
+ "max_concurrent_tasks": 6
193
+ },
194
+ {
195
+ "name": "cline",
196
+ "category": "code-agent",
197
+ "workflow_model": "interactive",
198
+ "tier": "A",
199
+ "has_mcp": true,
200
+ "has_hooks": true,
201
+ "has_skills": true,
202
+ "has_rules": true,
203
+ "instruction_file": ".clinerules/brainclaw.md",
204
+ "mcp_config_scope": "project",
205
+ "role_capabilities": [
206
+ "execute",
207
+ "review"
208
+ ],
209
+ "max_concurrent_tasks": 3
210
+ },
211
+ {
212
+ "name": "codex",
213
+ "category": "code-agent",
214
+ "workflow_model": "task-based",
215
+ "tier": "A",
216
+ "has_mcp": true,
217
+ "has_hooks": true,
218
+ "has_skills": true,
219
+ "has_rules": true,
220
+ "instruction_file": "AGENTS.md",
221
+ "mcp_config_scope": "machine",
222
+ "role_capabilities": [
223
+ "execute",
224
+ "review"
225
+ ],
226
+ "max_concurrent_tasks": 5
227
+ },
228
+ {
229
+ "name": "continue",
230
+ "category": "code-agent",
231
+ "workflow_model": "interactive",
232
+ "tier": "B",
233
+ "has_mcp": true,
234
+ "has_hooks": false,
235
+ "has_skills": false,
236
+ "has_rules": true,
237
+ "instruction_file": ".continue/rules/brainclaw.md",
238
+ "mcp_config_scope": "both",
239
+ "role_capabilities": [
240
+ "execute",
241
+ "consult"
242
+ ],
243
+ "max_concurrent_tasks": 2
244
+ },
245
+ {
246
+ "name": "cursor",
247
+ "category": "code-agent",
248
+ "workflow_model": "interactive",
249
+ "tier": "A",
250
+ "has_mcp": true,
251
+ "has_hooks": true,
252
+ "has_skills": true,
253
+ "has_rules": true,
254
+ "instruction_file": ".cursor/rules/brainclaw.md",
255
+ "mcp_config_scope": "machine",
256
+ "role_capabilities": [
257
+ "execute",
258
+ "review"
259
+ ],
260
+ "max_concurrent_tasks": 1
261
+ },
262
+ {
263
+ "name": "github-copilot",
264
+ "category": "code-agent",
265
+ "workflow_model": "interactive",
266
+ "tier": "A",
267
+ "has_mcp": true,
268
+ "has_hooks": true,
269
+ "has_skills": true,
270
+ "has_rules": true,
271
+ "instruction_file": ".github/copilot-instructions.md",
272
+ "mcp_config_scope": "project",
273
+ "role_capabilities": [
274
+ "execute",
275
+ "review",
276
+ "consult"
277
+ ],
278
+ "max_concurrent_tasks": 1
279
+ },
280
+ {
281
+ "name": "hermes",
282
+ "category": "autonomous-agent",
283
+ "workflow_model": "task-based",
284
+ "tier": "B",
285
+ "has_mcp": true,
286
+ "has_hooks": false,
287
+ "has_skills": true,
288
+ "has_rules": false,
289
+ "instruction_file": "AGENTS.md",
290
+ "mcp_config_scope": "machine",
291
+ "role_capabilities": [
292
+ "execute",
293
+ "review",
294
+ "consult"
295
+ ],
296
+ "max_concurrent_tasks": 1
297
+ },
298
+ {
299
+ "name": "kilocode",
300
+ "category": "code-agent",
301
+ "workflow_model": "interactive",
302
+ "tier": "B",
303
+ "has_mcp": true,
304
+ "has_hooks": false,
305
+ "has_skills": true,
306
+ "has_rules": true,
307
+ "instruction_file": ".kilo/rules/brainclaw.md",
308
+ "mcp_config_scope": "project",
309
+ "role_capabilities": [
310
+ "execute",
311
+ "review",
312
+ "consult"
313
+ ],
314
+ "max_concurrent_tasks": 2
315
+ },
316
+ {
317
+ "name": "mistral-vibe",
318
+ "category": "code-agent",
319
+ "workflow_model": "task-based",
320
+ "tier": "B",
321
+ "has_mcp": true,
322
+ "has_hooks": false,
323
+ "has_skills": true,
324
+ "has_rules": false,
325
+ "instruction_file": "AGENTS.md",
326
+ "mcp_config_scope": "both",
327
+ "role_capabilities": [
328
+ "execute",
329
+ "review",
330
+ "consult"
331
+ ],
332
+ "max_concurrent_tasks": 2
333
+ },
334
+ {
335
+ "name": "nanoclaw",
336
+ "category": "autonomous-agent",
337
+ "workflow_model": "task-based",
338
+ "tier": "C",
339
+ "has_mcp": false,
340
+ "has_hooks": false,
341
+ "has_skills": true,
342
+ "has_rules": false,
343
+ "instruction_file": "skills/nanoclaw/SKILL.md",
344
+ "mcp_config_scope": "none",
345
+ "role_capabilities": [
346
+ "execute"
347
+ ],
348
+ "max_concurrent_tasks": 1
349
+ },
350
+ {
351
+ "name": "nemoclaw",
352
+ "category": "autonomous-agent",
353
+ "workflow_model": "task-based",
354
+ "tier": "C",
355
+ "has_mcp": false,
356
+ "has_hooks": false,
357
+ "has_skills": true,
358
+ "has_rules": false,
359
+ "instruction_file": "skills/nemoclaw/SKILL.md",
360
+ "mcp_config_scope": "none",
361
+ "role_capabilities": [
362
+ "execute"
363
+ ],
364
+ "max_concurrent_tasks": 1
365
+ },
366
+ {
367
+ "name": "openclaw",
368
+ "category": "autonomous-agent",
369
+ "workflow_model": "task-based",
370
+ "tier": "B",
371
+ "has_mcp": true,
372
+ "has_hooks": false,
373
+ "has_skills": true,
374
+ "has_rules": false,
375
+ "instruction_file": "skills/openclaw/SKILL.md",
376
+ "mcp_config_scope": "machine",
377
+ "role_capabilities": [
378
+ "execute",
379
+ "coordinate"
380
+ ],
381
+ "max_concurrent_tasks": 1
382
+ },
383
+ {
384
+ "name": "opencode",
385
+ "category": "code-agent",
386
+ "workflow_model": "interactive",
387
+ "tier": "B",
388
+ "has_mcp": true,
389
+ "has_hooks": false,
390
+ "has_skills": false,
391
+ "has_rules": true,
392
+ "instruction_file": "AGENTS.md",
393
+ "mcp_config_scope": "project",
394
+ "role_capabilities": [
395
+ "execute",
396
+ "review"
397
+ ],
398
+ "max_concurrent_tasks": 2
399
+ },
400
+ {
401
+ "name": "picoclaw",
402
+ "category": "autonomous-agent",
403
+ "workflow_model": "scheduled",
404
+ "tier": "C",
405
+ "has_mcp": false,
406
+ "has_hooks": false,
407
+ "has_skills": true,
408
+ "has_rules": false,
409
+ "instruction_file": "skills/picoclaw/SKILL.md",
410
+ "mcp_config_scope": "none",
411
+ "role_capabilities": [
412
+ "execute"
413
+ ],
414
+ "max_concurrent_tasks": 1
415
+ },
416
+ {
417
+ "name": "roo",
418
+ "category": "code-agent",
419
+ "workflow_model": "interactive",
420
+ "tier": "B",
421
+ "has_mcp": true,
422
+ "has_hooks": false,
423
+ "has_skills": false,
424
+ "has_rules": true,
425
+ "instruction_file": ".roo/rules/brainclaw.md",
426
+ "mcp_config_scope": "project",
427
+ "role_capabilities": [
428
+ "execute",
429
+ "review"
430
+ ],
431
+ "max_concurrent_tasks": 2
432
+ },
433
+ {
434
+ "name": "windsurf",
435
+ "category": "code-agent",
436
+ "workflow_model": "interactive",
437
+ "tier": "A",
438
+ "has_mcp": true,
439
+ "has_hooks": true,
440
+ "has_skills": true,
441
+ "has_rules": true,
442
+ "instruction_file": ".windsurfrules",
443
+ "mcp_config_scope": "machine",
444
+ "role_capabilities": [
445
+ "execute",
446
+ "review"
447
+ ],
448
+ "max_concurrent_tasks": 1
449
+ },
450
+ {
451
+ "name": "zeroclaw",
452
+ "category": "autonomous-agent",
453
+ "workflow_model": "task-based",
454
+ "tier": "C",
455
+ "has_mcp": false,
456
+ "has_hooks": false,
457
+ "has_skills": true,
458
+ "has_rules": false,
459
+ "instruction_file": "skills/zeroclaw/SKILL.md",
460
+ "mcp_config_scope": "none",
461
+ "role_capabilities": [
462
+ "execute"
463
+ ],
464
+ "max_concurrent_tasks": 1
465
+ }
466
+ ]
112
467
  }
113
468
  }
114
469
  export default FACTS