brainclaw 0.29.2 → 1.5.3

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 (195) hide show
  1. package/README.md +193 -170
  2. package/dist/brainclaw-vscode.vsix +0 -0
  3. package/dist/cli.js +673 -24
  4. package/dist/commands/accept.js +3 -0
  5. package/dist/commands/add-step.js +11 -26
  6. package/dist/commands/agent-board.js +70 -3
  7. package/dist/commands/audit.js +19 -0
  8. package/dist/commands/check-policy.js +54 -0
  9. package/dist/commands/check-security-mcp.js +145 -0
  10. package/dist/commands/check-security.js +106 -0
  11. package/dist/commands/claim-resource.js +1 -0
  12. package/dist/commands/codev.js +672 -0
  13. package/dist/commands/compact.js +74 -0
  14. package/dist/commands/complete-step.js +16 -26
  15. package/dist/commands/constraint.js +8 -20
  16. package/dist/commands/decision.js +9 -20
  17. package/dist/commands/delete-plan.js +10 -12
  18. package/dist/commands/delete-step.js +16 -0
  19. package/dist/commands/dispatch.js +163 -0
  20. package/dist/commands/doctor.js +1122 -49
  21. package/dist/commands/enable-agent.js +1 -0
  22. package/dist/commands/export.js +280 -22
  23. package/dist/commands/handoff.js +33 -0
  24. package/dist/commands/harvest.js +189 -0
  25. package/dist/commands/hooks.js +82 -25
  26. package/dist/commands/inbox.js +169 -0
  27. package/dist/commands/init.js +38 -31
  28. package/dist/commands/install-hooks.js +71 -44
  29. package/dist/commands/link.js +89 -0
  30. package/dist/commands/list-claims.js +48 -3
  31. package/dist/commands/list-plans.js +129 -25
  32. package/dist/commands/loops-handlers.js +409 -0
  33. package/dist/commands/mcp-read-handlers.js +1628 -0
  34. package/dist/commands/mcp-schemas.generated.js +74 -0
  35. package/dist/commands/mcp.js +4221 -1501
  36. package/dist/commands/plan-resource.js +64 -0
  37. package/dist/commands/plan.js +12 -26
  38. package/dist/commands/prune.js +37 -2
  39. package/dist/commands/reflect.js +20 -7
  40. package/dist/commands/release-claim.js +11 -6
  41. package/dist/commands/release-notes.js +170 -0
  42. package/dist/commands/repair.js +210 -0
  43. package/dist/commands/run-profile.js +57 -0
  44. package/dist/commands/sequence.js +113 -0
  45. package/dist/commands/session-end.js +423 -14
  46. package/dist/commands/session-start.js +214 -41
  47. package/dist/commands/setup-security.js +103 -0
  48. package/dist/commands/setup.js +42 -4
  49. package/dist/commands/stale.js +109 -0
  50. package/dist/commands/switch.js +100 -2
  51. package/dist/commands/trap.js +14 -31
  52. package/dist/commands/update-handoff.js +63 -4
  53. package/dist/commands/update-plan.js +21 -28
  54. package/dist/commands/update-step.js +37 -0
  55. package/dist/commands/upgrade.js +313 -6
  56. package/dist/commands/usage.js +102 -0
  57. package/dist/commands/version.js +20 -0
  58. package/dist/commands/who.js +33 -5
  59. package/dist/commands/worktree.js +105 -0
  60. package/dist/core/actions.js +315 -0
  61. package/dist/core/agent-capability.js +610 -17
  62. package/dist/core/agent-context.js +7 -1
  63. package/dist/core/agent-files.js +1169 -85
  64. package/dist/core/agent-integrations.js +160 -5
  65. package/dist/core/agent-inventory.js +2 -0
  66. package/dist/core/agent-profiles.js +93 -0
  67. package/dist/core/agent-registry.js +162 -30
  68. package/dist/core/agentrun-reconciler.js +345 -0
  69. package/dist/core/agentruns.js +424 -0
  70. package/dist/core/ai-agent-detection.js +31 -10
  71. package/dist/core/archival.js +77 -0
  72. package/dist/core/assignment-sweeper.js +82 -0
  73. package/dist/core/assignments.js +367 -0
  74. package/dist/core/audit.js +30 -0
  75. package/dist/core/brainclaw-version.js +94 -2
  76. package/dist/core/candidates.js +93 -2
  77. package/dist/core/claims.js +419 -0
  78. package/dist/core/codev-metrics.js +77 -0
  79. package/dist/core/codev-personas.js +31 -0
  80. package/dist/core/codev-plan-gen.js +35 -0
  81. package/dist/core/codev-prompts.js +74 -0
  82. package/dist/core/codev-responses.js +62 -0
  83. package/dist/core/codev-rounds.js +218 -0
  84. package/dist/core/config.js +4 -0
  85. package/dist/core/context.js +381 -34
  86. package/dist/core/coordination.js +201 -6
  87. package/dist/core/cross-project.js +230 -16
  88. package/dist/core/default-profiles/doctor.yaml +11 -0
  89. package/dist/core/default-profiles/janitor.yaml +11 -0
  90. package/dist/core/default-profiles/onboarder.yaml +11 -0
  91. package/dist/core/default-profiles/reviewer.yaml +13 -0
  92. package/dist/core/dispatcher.js +1189 -0
  93. package/dist/core/duplicates.js +2 -2
  94. package/dist/core/entity-operations.js +450 -0
  95. package/dist/core/entity-registry.js +344 -0
  96. package/dist/core/events.js +106 -2
  97. package/dist/core/execution-adapters.js +154 -0
  98. package/dist/core/execution-context.js +63 -0
  99. package/dist/core/execution-profile.js +270 -0
  100. package/dist/core/execution.js +255 -0
  101. package/dist/core/facade-schema.js +81 -0
  102. package/dist/core/federation-cloud.js +99 -0
  103. package/dist/core/federation-message.js +52 -0
  104. package/dist/core/federation-transport.js +65 -0
  105. package/dist/core/gc-semantic.js +482 -0
  106. package/dist/core/governance.js +247 -0
  107. package/dist/core/guards.js +19 -0
  108. package/dist/core/ideation.js +72 -0
  109. package/dist/core/identity.js +110 -25
  110. package/dist/core/ids.js +6 -0
  111. package/dist/core/input-validation.js +2 -2
  112. package/dist/core/instruction-templates.js +344 -136
  113. package/dist/core/io.js +90 -11
  114. package/dist/core/lock.js +6 -2
  115. package/dist/core/loops/brief-assembly.js +213 -0
  116. package/dist/core/loops/facade-schema.js +148 -0
  117. package/dist/core/loops/index.js +7 -0
  118. package/dist/core/loops/iteration-engine.js +139 -0
  119. package/dist/core/loops/lock.js +385 -0
  120. package/dist/core/loops/store.js +201 -0
  121. package/dist/core/loops/types.js +403 -0
  122. package/dist/core/loops/verbs.js +534 -0
  123. package/dist/core/markdown.js +15 -3
  124. package/dist/core/memory-compactor.js +432 -0
  125. package/dist/core/memory-git.js +152 -8
  126. package/dist/core/messaging.js +278 -0
  127. package/dist/core/migration.js +32 -1
  128. package/dist/core/mutation-pipeline.js +4 -2
  129. package/dist/core/operations/memory-mutation.js +129 -0
  130. package/dist/core/operations/memory-write.js +78 -0
  131. package/dist/core/operations/plan.js +190 -0
  132. package/dist/core/policy.js +169 -0
  133. package/dist/core/reputation.js +9 -3
  134. package/dist/core/schema.js +491 -6
  135. package/dist/core/search.js +21 -2
  136. package/dist/core/security-cache.js +71 -0
  137. package/dist/core/security-guard.js +152 -0
  138. package/dist/core/security-scoring.js +86 -0
  139. package/dist/core/sequence.js +130 -0
  140. package/dist/core/socket-client.js +113 -0
  141. package/dist/core/staleness.js +246 -0
  142. package/dist/core/state.js +98 -22
  143. package/dist/core/store-resolution.js +43 -11
  144. package/dist/core/toml-writer.js +76 -0
  145. package/dist/core/upgrades/backup.js +232 -0
  146. package/dist/core/upgrades/health-check.js +169 -0
  147. package/dist/core/upgrades/patches/candidate-archive.js +145 -0
  148. package/dist/core/upgrades/patches/handoff-review-strip.js +128 -0
  149. package/dist/core/upgrades/patches/provenance-rollout.js +136 -0
  150. package/dist/core/upgrades/schema-version.js +97 -0
  151. package/dist/core/worktree.js +606 -0
  152. package/dist/facts.js +114 -0
  153. package/dist/facts.json +111 -0
  154. package/docs/architecture/project-refs.md +5 -1
  155. package/docs/cli.md +690 -43
  156. package/docs/concepts/ideation-loop.md +317 -0
  157. package/docs/concepts/loop-engine.md +456 -0
  158. package/docs/concepts/mcp-governance.md +268 -0
  159. package/docs/concepts/memory-staleness.md +122 -0
  160. package/docs/concepts/multi-agent-workflows.md +166 -0
  161. package/docs/concepts/plans-and-claims.md +31 -6
  162. package/docs/concepts/project-md-convention.md +35 -0
  163. package/docs/concepts/troubleshooting.md +220 -0
  164. package/docs/concepts/upgrade-cli.md +202 -0
  165. package/docs/concepts/upgrade-dogfood-procedure.md +114 -0
  166. package/docs/context-format-changelog.md +2 -2
  167. package/docs/context-format.md +2 -2
  168. package/docs/index.md +68 -0
  169. package/docs/integrations/agents.md +15 -16
  170. package/docs/integrations/cline.md +88 -0
  171. package/docs/integrations/codex.md +75 -23
  172. package/docs/integrations/continue.md +60 -0
  173. package/docs/integrations/copilot.md +67 -9
  174. package/docs/integrations/kilocode.md +72 -0
  175. package/docs/integrations/mcp.md +304 -21
  176. package/docs/integrations/mistral-vibe.md +122 -0
  177. package/docs/integrations/opencode.md +84 -0
  178. package/docs/integrations/overview.md +23 -8
  179. package/docs/integrations/roo.md +74 -0
  180. package/docs/integrations/windsurf.md +83 -0
  181. package/docs/mcp-schema-changelog.md +191 -1
  182. package/docs/playbooks/integration/index.md +121 -0
  183. package/docs/playbooks/productivity/index.md +102 -0
  184. package/docs/playbooks/team/index.md +122 -0
  185. package/docs/product/agent-first-model.md +184 -0
  186. package/docs/product/entity-model-audit.md +462 -0
  187. package/docs/quickstart-existing-project.md +135 -0
  188. package/docs/quickstart.md +124 -37
  189. package/docs/release-maintenance.md +79 -0
  190. package/docs/review.md +2 -0
  191. package/docs/server-operations.md +118 -0
  192. package/package.json +20 -12
  193. package/dist/commands/claude-desktop-extension.js +0 -18
  194. package/dist/commands/diff.js +0 -99
  195. package/dist/core/claude-desktop-extension.js +0 -224
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ export const ExecutionStatusSchema = z.enum(['delivered_and_started', 'command_ready_manual', 'inbox_only']);
3
+ export const WorkIntentSchema = z.enum(['execute', 'consult', 'resume', 'review']);
4
+ // pln#492 phase 2.c — 'ideate' opens an ideation loop with a proposal seed
5
+ // artifact. The handler does NOT yet dispatch turns (driver wire-up is
6
+ // phase 2.d). Callers receive loop_id and may drive the loop manually via
7
+ // bclaw_loop intent='turn' / 'advance' until the dispatch path lands.
8
+ export const CoordinateIntentSchema = z.enum(['assign', 'consult', 'review', 'reroute', 'summarize', 'ideate']);
9
+ export const WorkRequestSchema = z.object({
10
+ intent: WorkIntentSchema,
11
+ scope: z.string().optional(),
12
+ planId: z.string().optional(),
13
+ task: z.string().optional(),
14
+ messageId: z.string().optional(),
15
+ contextTarget: z.string().optional(),
16
+ compact: z.boolean().optional().default(true),
17
+ });
18
+ export const CoordinateRequestSchema = z.object({
19
+ intent: CoordinateIntentSchema,
20
+ task: z.string(),
21
+ scope: z.string().optional(),
22
+ targetAgents: z.array(z.string()).optional(),
23
+ constraints: z.record(z.string(), z.unknown()).optional(),
24
+ threadId: z.string().optional(),
25
+ autoExecute: z.boolean().optional(),
26
+ /**
27
+ * When intent=review and open_loop=true, a review Loop is opened on top of
28
+ * the review candidate: author slot = caller, reviewer slots = targetAgents.
29
+ * The candidate is linked as a change_summary artifact and the loop is
30
+ * advanced to `findings`, emitting a `turn_assigned` event for each
31
+ * reviewer slot. Default false for strict backward compatibility with
32
+ * existing `review` callers. See docs/concepts/loop-engine.md §Automation.
33
+ */
34
+ open_loop: z.boolean().optional(),
35
+ /**
36
+ * Optional override: asymmetric (classical author→reviewer handoff) or
37
+ * symmetric (each reviewer turn may apply fixes, halving round-trips).
38
+ * Ignored when open_loop is false. Defaults to asymmetric.
39
+ */
40
+ review_mode: z.enum(['asymmetric', 'symmetric']).optional(),
41
+ /**
42
+ * Caller-minted ULID/UUIDv7 for idempotent retries. Today this is observed
43
+ * on intent='review' + open_loop=true: a retry with the same
44
+ * client_request_id returns the cached {candidate_id, loop_id} response
45
+ * without creating a duplicate candidate + loop. Safe to pass on other
46
+ * intents — silently ignored.
47
+ */
48
+ client_request_id: z.string().min(1).optional(),
49
+ /**
50
+ * pln#359 phase 1b — route the dispatch into a linked project. When set,
51
+ * claim, assignment, and inbox message all land in the target project
52
+ * (resolved via resolveProjectCwd against cross_project_links + workspace
53
+ * store-chain children). Auto-spawn is disabled when project is set —
54
+ * the target agent picks up the brief async via its own bclaw_work.
55
+ */
56
+ project: z.string().optional(),
57
+ });
58
+ export const FacadeArtifactSchema = z.object({
59
+ type: z.string(),
60
+ id: z.string(),
61
+ path: z.string().optional(),
62
+ });
63
+ export const FacadeSideEffectSchema = z.object({
64
+ action: z.string(),
65
+ entity: z.string(),
66
+ id: z.string(),
67
+ });
68
+ export const FacadeResponseSchema = z.object({
69
+ status: z.enum(['ok', 'error', 'partial']),
70
+ intent: z.string(),
71
+ result: z.unknown(),
72
+ artifacts: z.array(FacadeArtifactSchema),
73
+ side_effects: z.array(FacadeSideEffectSchema),
74
+ error: z.string().optional(),
75
+ duration_ms: z.number().optional(),
76
+ claim_status: z.enum(['created', 'existing', 'none']).optional(),
77
+ session_id: z.string().optional(),
78
+ warnings: z.array(z.string()),
79
+ execution_status: ExecutionStatusSchema.optional(),
80
+ });
81
+ //# sourceMappingURL=facade-schema.js.map
@@ -0,0 +1,99 @@
1
+ import { loadConfig } from './config.js';
2
+ import { logger } from './logger.js';
3
+ const DEFAULT_API_URL = 'https://app.brainclaw.dev';
4
+ function resolveCloudConfig(cwd) {
5
+ // Check env vars first
6
+ const apiUrl = process.env.BRAINCLAW_CLOUD_URL ?? DEFAULT_API_URL;
7
+ const apiKey = process.env.BRAINCLAW_CLOUD_API_KEY;
8
+ if (apiKey) {
9
+ return { apiUrl, apiKey };
10
+ }
11
+ // Check config.yaml
12
+ try {
13
+ const config = loadConfig(cwd);
14
+ const cloud = config.cloud;
15
+ if (cloud?.api_key) {
16
+ return { apiUrl: cloud.api_url ?? apiUrl, apiKey: cloud.api_key };
17
+ }
18
+ }
19
+ catch {
20
+ // No config — cloud not configured
21
+ }
22
+ return undefined;
23
+ }
24
+ export async function pushSignalToCloud(message, cwd) {
25
+ const cloud = resolveCloudConfig(cwd);
26
+ if (!cloud) {
27
+ logger.debug('Cloud not configured — skipping push');
28
+ return false;
29
+ }
30
+ try {
31
+ const response = await fetch(`${cloud.apiUrl}/api/v1/messages`, {
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ 'X-API-Key': cloud.apiKey,
36
+ },
37
+ body: JSON.stringify(message),
38
+ });
39
+ if (!response.ok) {
40
+ logger.debug(`Cloud push failed: ${response.status} ${response.statusText}`);
41
+ return false;
42
+ }
43
+ return true;
44
+ }
45
+ catch (err) {
46
+ logger.debug('Cloud push error:', err);
47
+ return false;
48
+ }
49
+ }
50
+ export async function pullSignalsFromCloud(agentName, options, cwd) {
51
+ const cloud = resolveCloudConfig(cwd);
52
+ if (!cloud) {
53
+ return [];
54
+ }
55
+ try {
56
+ const params = new URLSearchParams();
57
+ if (options?.since)
58
+ params.set('since', options.since);
59
+ if (options?.limit)
60
+ params.set('limit', String(options.limit));
61
+ const url = `${cloud.apiUrl}/api/v1/inbox/${encodeURIComponent(agentName)}?${params}`;
62
+ const response = await fetch(url, {
63
+ headers: { 'X-API-Key': cloud.apiKey },
64
+ });
65
+ if (!response.ok) {
66
+ logger.debug(`Cloud pull failed: ${response.status}`);
67
+ return [];
68
+ }
69
+ const data = (await response.json());
70
+ return data.messages ?? [];
71
+ }
72
+ catch (err) {
73
+ logger.debug('Cloud pull error:', err);
74
+ return [];
75
+ }
76
+ }
77
+ export async function pushBoardToCloud(projectName, boardData, cwd) {
78
+ const cloud = resolveCloudConfig(cwd);
79
+ if (!cloud)
80
+ return false;
81
+ try {
82
+ const response = await fetch(`${cloud.apiUrl}/api/v1/board/${encodeURIComponent(projectName)}`, {
83
+ method: 'POST',
84
+ headers: {
85
+ 'Content-Type': 'application/json',
86
+ 'X-API-Key': cloud.apiKey,
87
+ },
88
+ body: JSON.stringify(boardData),
89
+ });
90
+ return response.ok;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ export function isCloudConfigured(cwd) {
97
+ return resolveCloudConfig(cwd) !== undefined;
98
+ }
99
+ //# sourceMappingURL=federation-cloud.js.map
@@ -0,0 +1,52 @@
1
+ import crypto from 'node:crypto';
2
+ import { z } from 'zod';
3
+ import { generateId, nowISO } from './ids.js';
4
+ export const FederationMessageSchema = z.object({
5
+ schema_version: z.literal(1),
6
+ id: z.string(),
7
+ version: z.number().int().min(1),
8
+ idempotency_key: z.string(),
9
+ from: z.object({
10
+ project_id: z.string().optional(),
11
+ project_name: z.string(),
12
+ project_path: z.string(),
13
+ agent_name: z.string(),
14
+ agent_id: z.string().optional(),
15
+ host_id: z.string().optional(),
16
+ }),
17
+ to: z.object({
18
+ project_name: z.string(),
19
+ project_path: z.string(),
20
+ agent_name: z.string().optional(),
21
+ }),
22
+ type: z.enum(['signal', 'handoff', 'candidate', 'runtime_note', 'board_snapshot']),
23
+ payload: z.unknown(),
24
+ created_at: z.string(),
25
+ causal_parent: z.string().optional(),
26
+ });
27
+ function computeIdempotencyKey(msg) {
28
+ const data = JSON.stringify({ from: msg.from, to: msg.to, type: msg.type, payload: msg.payload });
29
+ return crypto.createHash('sha256').update(data).digest('hex').slice(0, 16);
30
+ }
31
+ export function createFederationMessage(input) {
32
+ return {
33
+ ...input,
34
+ schema_version: 1,
35
+ id: generateId('msg'),
36
+ created_at: nowISO(),
37
+ idempotency_key: computeIdempotencyKey(input),
38
+ };
39
+ }
40
+ export function validateMessage(raw) {
41
+ return FederationMessageSchema.parse(raw);
42
+ }
43
+ export function serializeMessage(msg) {
44
+ return JSON.stringify(msg, null, 2);
45
+ }
46
+ export function deserializeMessage(raw) {
47
+ return validateMessage(JSON.parse(raw));
48
+ }
49
+ export function isDuplicate(existing, incoming) {
50
+ return existing.some((m) => m.idempotency_key === incoming.idempotency_key);
51
+ }
52
+ //# sourceMappingURL=federation-message.js.map
@@ -0,0 +1,65 @@
1
+ import { validateMessage, serializeMessage, deserializeMessage, } from './federation-message.js';
2
+ import { loadConfig } from './config.js';
3
+ import { memoryDir } from './io.js';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ function signalInboxDir(projectPath) {
7
+ return path.join(memoryDir(projectPath), 'coordination', 'inbox', 'cross-project');
8
+ }
9
+ export function pushSignal(targetProjectPath, message) {
10
+ validateMessage(message);
11
+ const dir = signalInboxDir(targetProjectPath);
12
+ const filepath = path.join(dir, `${message.id}.json`);
13
+ if (fs.existsSync(filepath))
14
+ return;
15
+ fs.mkdirSync(dir, { recursive: true });
16
+ fs.writeFileSync(filepath, serializeMessage(message) + '\n', 'utf-8');
17
+ }
18
+ export function pullSignals(sourceProjectPath, options) {
19
+ const dir = signalInboxDir(sourceProjectPath);
20
+ if (!fs.existsSync(dir))
21
+ return [];
22
+ const messages = [];
23
+ for (const entry of fs.readdirSync(dir)) {
24
+ if (!entry.endsWith('.json'))
25
+ continue;
26
+ try {
27
+ const msg = deserializeMessage(fs.readFileSync(path.join(dir, entry), 'utf-8'));
28
+ if (options?.since && msg.created_at <= options.since)
29
+ continue;
30
+ messages.push(msg);
31
+ }
32
+ catch { /* skip invalid files */ }
33
+ }
34
+ return messages.sort((a, b) => a.created_at.localeCompare(b.created_at));
35
+ }
36
+ export function pullSignalsFromLinkedProjects(cwd) {
37
+ let config;
38
+ try {
39
+ config = loadConfig(cwd);
40
+ }
41
+ catch {
42
+ return [];
43
+ }
44
+ const baseCwd = cwd ?? process.cwd();
45
+ const all = [];
46
+ for (const link of config.cross_project_links ?? []) {
47
+ if (link.role !== 'subscriber' && link.role !== 'publisher')
48
+ continue;
49
+ const absolutePath = path.isAbsolute(link.path)
50
+ ? link.path
51
+ : path.resolve(baseCwd, link.path);
52
+ try {
53
+ all.push(...pullSignals(absolutePath));
54
+ }
55
+ catch { /* unavailable project — skip */ }
56
+ }
57
+ return all.sort((a, b) => a.created_at.localeCompare(b.created_at));
58
+ }
59
+ export function markSignalProcessed(projectPath, messageId) {
60
+ const dir = signalInboxDir(projectPath);
61
+ const processedDir = path.join(dir, '.processed');
62
+ fs.mkdirSync(processedDir, { recursive: true });
63
+ fs.renameSync(path.join(dir, `${messageId}.json`), path.join(processedDir, `${messageId}.json`));
64
+ }
65
+ //# sourceMappingURL=federation-transport.js.map