brainclaw 0.25.3 → 0.28.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.
- package/README.md +14 -1
- package/dist/cli.js +32 -2
- package/dist/commands/capability.js +21 -32
- package/dist/commands/check-events.js +36 -0
- package/dist/commands/discover.js +21 -0
- package/dist/commands/doctor.js +67 -11
- package/dist/commands/explore.js +7 -10
- package/dist/commands/hooks.js +33 -17
- package/dist/commands/mcp.js +380 -70
- package/dist/commands/migrate.js +75 -0
- package/dist/commands/tool.js +29 -39
- package/dist/core/agent-capability.js +55 -110
- package/dist/core/agent-files.js +13 -0
- package/dist/core/agent-integrations.js +17 -0
- package/dist/core/context.js +102 -8
- package/dist/core/coordination.js +25 -0
- package/dist/core/io.js +2 -0
- package/dist/core/migration.js +3 -1
- package/dist/core/project-discovery.js +236 -0
- package/dist/core/registries.js +120 -0
- package/dist/core/schema.js +11 -2
- package/docs/integrations/agents.md +10 -3
- package/package.json +7 -1
package/dist/core/migration.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import YAML from 'yaml';
|
|
4
4
|
import { memoryDir, memoryPath, readFileSync, writeFileAtomic, resolveEntityDir } from './io.js';
|
|
5
|
-
import { BootstrapApplicationReceiptSchema, BootstrapImportPlanDocumentSchema, AgentIdentityDocumentSchema, BootstrapProfileDocumentSchema, CandidateSchema, ClaimSchema, ConfigSchema, MemorySeedDocumentSchema, ConstraintSchema, CurrentSessionStateSchema, DecisionSchema, HandoffSchema, InstructionEntrySchema, PlanItemSchema, ProjectIdentityDocumentSchema, RuntimeNoteSchema, SessionSnapshotSchema, TrapSchema, AiSurfaceTaskRequestSchema, } from './schema.js';
|
|
5
|
+
import { BootstrapApplicationReceiptSchema, BootstrapImportPlanDocumentSchema, AgentIdentityDocumentSchema, BootstrapProfileDocumentSchema, CandidateSchema, ClaimSchema, ConfigSchema, MemorySeedDocumentSchema, ConstraintSchema, CurrentSessionStateSchema, DecisionSchema, HandoffSchema, InstructionEntrySchema, PlanItemSchema, ProjectIdentityDocumentSchema, RuntimeNoteSchema, SessionSnapshotSchema, TrapSchema, AiSurfaceTaskRequestSchema, ProjectCapabilitySchema, ProjectToolSchema, } from './schema.js';
|
|
6
6
|
export class MigrationError extends Error {
|
|
7
7
|
kind;
|
|
8
8
|
documentType;
|
|
@@ -33,6 +33,8 @@ const registry = {
|
|
|
33
33
|
runtime_note: createRegistryEntry(RuntimeNoteSchema),
|
|
34
34
|
ai_surface_task: createRegistryEntry(AiSurfaceTaskRequestSchema),
|
|
35
35
|
session_snapshot: createRegistryEntry(SessionSnapshotSchema),
|
|
36
|
+
capability: createRegistryEntry(ProjectCapabilitySchema),
|
|
37
|
+
tool: createRegistryEntry(ProjectToolSchema),
|
|
36
38
|
trap: createRegistryEntry(TrapSchema),
|
|
37
39
|
};
|
|
38
40
|
function createRegistryEntry(schema) {
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project discovery — unified workspace inventory that composes existing
|
|
3
|
+
* scan functions into a single structured profile.
|
|
4
|
+
*
|
|
5
|
+
* Boundary: discovery describes what exists in the workspace RIGHT NOW.
|
|
6
|
+
* It is NOT canonical memory (decisions, traps, plans). It is NOT
|
|
7
|
+
* machine profile (shells, SSH keys, WSL distros). It is the project-level
|
|
8
|
+
* answer to "what MCP servers, skills, hooks, instruction files, and
|
|
9
|
+
* agent integrations are available in this workspace?"
|
|
10
|
+
*/
|
|
11
|
+
import fs from 'node:fs';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { buildAgentToolingContext } from './agent-context.js';
|
|
14
|
+
import { assessAgentIntegrationReadiness } from './agent-integrations.js';
|
|
15
|
+
import { loadConfig } from './config.js';
|
|
16
|
+
import { memoryDir } from './io.js';
|
|
17
|
+
import { nowISO } from './ids.js';
|
|
18
|
+
// --- Native instruction file discovery (extracted from bootstrap.ts) ---
|
|
19
|
+
const NATIVE_INSTRUCTION_FILES = [
|
|
20
|
+
'AGENTS.md',
|
|
21
|
+
'CLAUDE.md',
|
|
22
|
+
'GEMINI.md',
|
|
23
|
+
'.windsurfrules',
|
|
24
|
+
'.github/copilot-instructions.md',
|
|
25
|
+
];
|
|
26
|
+
const NATIVE_INSTRUCTION_DIRS = [
|
|
27
|
+
'.cursor/rules',
|
|
28
|
+
'.roo/rules',
|
|
29
|
+
'.continue/rules',
|
|
30
|
+
'.clinerules',
|
|
31
|
+
];
|
|
32
|
+
// MCP config files that agents use
|
|
33
|
+
const MCP_CONFIG_FILES = [
|
|
34
|
+
'.mcp.json',
|
|
35
|
+
'opencode.json',
|
|
36
|
+
'.cursor/mcp.json',
|
|
37
|
+
'.roo/mcp.json',
|
|
38
|
+
'.continue/config.json',
|
|
39
|
+
];
|
|
40
|
+
// Hook config files
|
|
41
|
+
const HOOK_CONFIG_FILES = [
|
|
42
|
+
'.claude/settings.local.json',
|
|
43
|
+
'.cursor/rules/brainclaw-session.mdc',
|
|
44
|
+
];
|
|
45
|
+
export function buildProjectDiscovery(options = {}) {
|
|
46
|
+
const cwd = options.cwd ?? process.cwd();
|
|
47
|
+
const env = options.env ?? process.env;
|
|
48
|
+
// 1. Agent tooling (AGENTS.md, skills, MCP servers)
|
|
49
|
+
const agentTooling = buildAgentToolingContext({ cwd, env });
|
|
50
|
+
// 2. Native instruction files
|
|
51
|
+
const instructionFiles = discoverFiles(cwd, NATIVE_INSTRUCTION_FILES, NATIVE_INSTRUCTION_DIRS);
|
|
52
|
+
// 3. MCP config files
|
|
53
|
+
const mcpConfigs = discoverStaticFiles(cwd, MCP_CONFIG_FILES);
|
|
54
|
+
// 4. Hook config files
|
|
55
|
+
const hookConfigs = discoverStaticFiles(cwd, HOOK_CONFIG_FILES);
|
|
56
|
+
// 5. Integration readiness
|
|
57
|
+
let integrations = [];
|
|
58
|
+
try {
|
|
59
|
+
const config = loadConfig(cwd);
|
|
60
|
+
integrations = assessAgentIntegrationReadiness(config, cwd, env);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// config may not exist yet
|
|
64
|
+
}
|
|
65
|
+
const foundInstructions = instructionFiles.filter(f => f.exists);
|
|
66
|
+
const foundMcpConfigs = mcpConfigs.filter(f => f.exists);
|
|
67
|
+
const foundHookConfigs = hookConfigs.filter(f => f.exists);
|
|
68
|
+
return {
|
|
69
|
+
discovered_at: nowISO(),
|
|
70
|
+
workspace_root: cwd,
|
|
71
|
+
agent_tooling: agentTooling,
|
|
72
|
+
instruction_files: foundInstructions,
|
|
73
|
+
mcp_configs: foundMcpConfigs,
|
|
74
|
+
hook_configs: foundHookConfigs,
|
|
75
|
+
integrations,
|
|
76
|
+
summary: {
|
|
77
|
+
total_instruction_files: foundInstructions.length,
|
|
78
|
+
total_mcp_servers: agentTooling.mcp_servers.length,
|
|
79
|
+
total_skills: agentTooling.skills.length,
|
|
80
|
+
total_mcp_configs: foundMcpConfigs.length,
|
|
81
|
+
total_hook_configs: foundHookConfigs.length,
|
|
82
|
+
integrations_ready: integrations.filter(i => i.ready).length,
|
|
83
|
+
integrations_total: integrations.length,
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
// --- Persistence ---
|
|
88
|
+
const DISCOVERY_PROFILE_FILE = 'discovery-profile.json';
|
|
89
|
+
export function saveDiscoveryProfile(profile, cwd) {
|
|
90
|
+
const dir = path.join(memoryDir(cwd), 'discovery');
|
|
91
|
+
if (!fs.existsSync(dir)) {
|
|
92
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
93
|
+
}
|
|
94
|
+
const filePath = path.join(dir, DISCOVERY_PROFILE_FILE);
|
|
95
|
+
fs.writeFileSync(filePath, JSON.stringify(profile, null, 2), 'utf-8');
|
|
96
|
+
}
|
|
97
|
+
export function loadDiscoveryProfile(cwd) {
|
|
98
|
+
const filePath = path.join(memoryDir(cwd), 'discovery', DISCOVERY_PROFILE_FILE);
|
|
99
|
+
if (!fs.existsSync(filePath))
|
|
100
|
+
return undefined;
|
|
101
|
+
try {
|
|
102
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// --- Rendering ---
|
|
109
|
+
export function renderDiscoverySummary(profile) {
|
|
110
|
+
const lines = [];
|
|
111
|
+
const s = profile.summary;
|
|
112
|
+
lines.push('# Project Discovery');
|
|
113
|
+
lines.push(`Discovered at: ${profile.discovered_at}`);
|
|
114
|
+
lines.push('');
|
|
115
|
+
// Instruction files
|
|
116
|
+
if (profile.instruction_files.length > 0) {
|
|
117
|
+
lines.push(`## Instruction Files (${s.total_instruction_files})`);
|
|
118
|
+
for (const f of profile.instruction_files) {
|
|
119
|
+
const managed = f.managed_by_brainclaw ? ' (managed)' : '';
|
|
120
|
+
lines.push(` ${f.path}${managed}`);
|
|
121
|
+
}
|
|
122
|
+
lines.push('');
|
|
123
|
+
}
|
|
124
|
+
// MCP configs
|
|
125
|
+
if (profile.mcp_configs.length > 0) {
|
|
126
|
+
lines.push(`## MCP Configs (${s.total_mcp_configs})`);
|
|
127
|
+
for (const f of profile.mcp_configs) {
|
|
128
|
+
lines.push(` ${f.path}`);
|
|
129
|
+
}
|
|
130
|
+
lines.push('');
|
|
131
|
+
}
|
|
132
|
+
// MCP servers (from agent tooling)
|
|
133
|
+
if (s.total_mcp_servers > 0) {
|
|
134
|
+
lines.push(`## MCP Servers (${s.total_mcp_servers})`);
|
|
135
|
+
for (const server of profile.agent_tooling.mcp_servers) {
|
|
136
|
+
lines.push(` ${server.name} (${server.transport}, ${server.availability})`);
|
|
137
|
+
}
|
|
138
|
+
lines.push('');
|
|
139
|
+
}
|
|
140
|
+
// Skills
|
|
141
|
+
if (s.total_skills > 0) {
|
|
142
|
+
lines.push(`## Skills (${s.total_skills})`);
|
|
143
|
+
for (const skill of profile.agent_tooling.skills.slice(0, 10)) {
|
|
144
|
+
lines.push(` ${skill.name}${skill.description ? `: ${skill.description}` : ''}`);
|
|
145
|
+
}
|
|
146
|
+
if (s.total_skills > 10) {
|
|
147
|
+
lines.push(` ... and ${s.total_skills - 10} more`);
|
|
148
|
+
}
|
|
149
|
+
lines.push('');
|
|
150
|
+
}
|
|
151
|
+
// Hook configs
|
|
152
|
+
if (profile.hook_configs.length > 0) {
|
|
153
|
+
lines.push(`## Hook Configs (${s.total_hook_configs})`);
|
|
154
|
+
for (const f of profile.hook_configs) {
|
|
155
|
+
lines.push(` ${f.path}`);
|
|
156
|
+
}
|
|
157
|
+
lines.push('');
|
|
158
|
+
}
|
|
159
|
+
// Integrations
|
|
160
|
+
if (profile.integrations.length > 0) {
|
|
161
|
+
lines.push(`## Agent Integrations (${s.integrations_ready}/${s.integrations_total} ready)`);
|
|
162
|
+
for (const integ of profile.integrations) {
|
|
163
|
+
const status = integ.ready ? '✔' : '✗';
|
|
164
|
+
const missing = integ.missing_surfaces.length > 0
|
|
165
|
+
? ` — missing: ${integ.missing_surfaces.map(s => s.kind).join(', ')}`
|
|
166
|
+
: '';
|
|
167
|
+
lines.push(` ${status} ${integ.agent_name}${missing}`);
|
|
168
|
+
}
|
|
169
|
+
lines.push('');
|
|
170
|
+
}
|
|
171
|
+
if (s.total_instruction_files + s.total_mcp_servers + s.total_skills === 0) {
|
|
172
|
+
lines.push('No integration surfaces detected.');
|
|
173
|
+
}
|
|
174
|
+
return lines.join('\n');
|
|
175
|
+
}
|
|
176
|
+
// --- Helpers ---
|
|
177
|
+
function discoverStaticFiles(cwd, files) {
|
|
178
|
+
const results = [];
|
|
179
|
+
for (const relativePath of files) {
|
|
180
|
+
const fullPath = path.join(cwd, relativePath);
|
|
181
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
182
|
+
const stat = fs.statSync(fullPath);
|
|
183
|
+
results.push({
|
|
184
|
+
path: relativePath,
|
|
185
|
+
exists: true,
|
|
186
|
+
size: stat.size,
|
|
187
|
+
managed_by_brainclaw: isManagedByBrainclaw(fullPath),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return results;
|
|
192
|
+
}
|
|
193
|
+
function discoverFiles(cwd, files, dirs) {
|
|
194
|
+
const results = [];
|
|
195
|
+
for (const relativePath of files) {
|
|
196
|
+
const fullPath = path.join(cwd, relativePath);
|
|
197
|
+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isFile()) {
|
|
198
|
+
results.push({
|
|
199
|
+
path: relativePath,
|
|
200
|
+
exists: true,
|
|
201
|
+
size: fs.statSync(fullPath).size,
|
|
202
|
+
managed_by_brainclaw: isManagedByBrainclaw(fullPath),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
for (const relativeDir of dirs) {
|
|
207
|
+
const dir = path.join(cwd, relativeDir);
|
|
208
|
+
if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory())
|
|
209
|
+
continue;
|
|
210
|
+
for (const entry of fs.readdirSync(dir).sort()) {
|
|
211
|
+
if (!/\.(md|mdc)$/i.test(entry))
|
|
212
|
+
continue;
|
|
213
|
+
const relativePath = path.posix.join(relativeDir.replace(/\\/g, '/'), entry);
|
|
214
|
+
const fullPath = path.join(cwd, relativePath);
|
|
215
|
+
results.push({
|
|
216
|
+
path: relativePath,
|
|
217
|
+
exists: true,
|
|
218
|
+
size: fs.statSync(fullPath).size,
|
|
219
|
+
managed_by_brainclaw: isManagedByBrainclaw(fullPath),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return results;
|
|
224
|
+
}
|
|
225
|
+
function isManagedByBrainclaw(filePath) {
|
|
226
|
+
try {
|
|
227
|
+
const content = fs.readFileSync(filePath, 'utf-8').slice(0, 200);
|
|
228
|
+
return content.includes('brainclaw') && (content.includes('Managed by brainclaw') ||
|
|
229
|
+
content.includes('BRAINCLAW_SECTION') ||
|
|
230
|
+
content.includes('brainclaw export'));
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=project-discovery.js.map
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedicated registries for project capabilities and tools.
|
|
3
|
+
*
|
|
4
|
+
* Replaces the legacy hack of storing capabilities/tools as decisions
|
|
5
|
+
* with 'capability'/'tool' tags. Items are now persisted as individual
|
|
6
|
+
* JSON files under discovery/capabilities/ and discovery/tools/.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { resolveEntityDir } from './io.js';
|
|
11
|
+
import { loadVersionedJsonFile, saveVersionedJsonFile } from './migration.js';
|
|
12
|
+
import { ProjectCapabilitySchema, ProjectToolSchema } from './schema.js';
|
|
13
|
+
import { generateIdWithLabel, nowISO } from './ids.js';
|
|
14
|
+
import { appendEvent } from './event-log.js';
|
|
15
|
+
// --- Capabilities ---
|
|
16
|
+
export function listCapabilities(cwd) {
|
|
17
|
+
const dir = resolveEntityDir('capabilities', cwd, 'read');
|
|
18
|
+
if (!dir || !fs.existsSync(dir))
|
|
19
|
+
return [];
|
|
20
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
21
|
+
const items = [];
|
|
22
|
+
for (const file of files) {
|
|
23
|
+
try {
|
|
24
|
+
const result = loadVersionedJsonFile('capability', path.join(dir, file));
|
|
25
|
+
items.push(ProjectCapabilitySchema.parse(result.document));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// skip invalid
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return items;
|
|
32
|
+
}
|
|
33
|
+
export function saveCapability(cap, cwd) {
|
|
34
|
+
const dir = resolveEntityDir('capabilities', cwd, 'write');
|
|
35
|
+
if (!fs.existsSync(dir))
|
|
36
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
37
|
+
saveVersionedJsonFile('capability', path.join(dir, `${cap.id}.json`), cap);
|
|
38
|
+
}
|
|
39
|
+
export function deleteCapability(id, cwd) {
|
|
40
|
+
const dir = resolveEntityDir('capabilities', cwd, 'read');
|
|
41
|
+
if (!dir)
|
|
42
|
+
return false;
|
|
43
|
+
const fp = path.join(dir, `${id}.json`);
|
|
44
|
+
if (!fs.existsSync(fp))
|
|
45
|
+
return false;
|
|
46
|
+
fs.unlinkSync(fp);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
export function createCapability(opts, cwd) {
|
|
50
|
+
const idObj = generateIdWithLabel('cap');
|
|
51
|
+
const cap = {
|
|
52
|
+
id: idObj.id,
|
|
53
|
+
name: opts.name,
|
|
54
|
+
description: opts.description,
|
|
55
|
+
category: opts.category ?? 'general',
|
|
56
|
+
tags: opts.tags ?? [],
|
|
57
|
+
status: 'stable',
|
|
58
|
+
created_at: nowISO(),
|
|
59
|
+
author: opts.author,
|
|
60
|
+
author_id: opts.authorId,
|
|
61
|
+
model: opts.model,
|
|
62
|
+
};
|
|
63
|
+
saveCapability(cap, cwd);
|
|
64
|
+
appendEvent({ action: 'create', item_type: 'decision', item_id: cap.id, agent: opts.author, agent_id: opts.authorId, summary: `capability: ${opts.name}` }, cwd);
|
|
65
|
+
return cap;
|
|
66
|
+
}
|
|
67
|
+
// --- Tools ---
|
|
68
|
+
export function listTools(cwd) {
|
|
69
|
+
const dir = resolveEntityDir('tools', cwd, 'read');
|
|
70
|
+
if (!dir || !fs.existsSync(dir))
|
|
71
|
+
return [];
|
|
72
|
+
const files = fs.readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
73
|
+
const items = [];
|
|
74
|
+
for (const file of files) {
|
|
75
|
+
try {
|
|
76
|
+
const result = loadVersionedJsonFile('tool', path.join(dir, file));
|
|
77
|
+
items.push(ProjectToolSchema.parse(result.document));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// skip invalid
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return items;
|
|
84
|
+
}
|
|
85
|
+
export function saveTool(tool, cwd) {
|
|
86
|
+
const dir = resolveEntityDir('tools', cwd, 'write');
|
|
87
|
+
if (!fs.existsSync(dir))
|
|
88
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
89
|
+
saveVersionedJsonFile('tool', path.join(dir, `${tool.id}.json`), tool);
|
|
90
|
+
}
|
|
91
|
+
export function deleteTool(id, cwd) {
|
|
92
|
+
const dir = resolveEntityDir('tools', cwd, 'read');
|
|
93
|
+
if (!dir)
|
|
94
|
+
return false;
|
|
95
|
+
const fp = path.join(dir, `${id}.json`);
|
|
96
|
+
if (!fs.existsSync(fp))
|
|
97
|
+
return false;
|
|
98
|
+
fs.unlinkSync(fp);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
export function createTool(opts, cwd) {
|
|
102
|
+
const idObj = generateIdWithLabel('tol');
|
|
103
|
+
const tool = {
|
|
104
|
+
id: idObj.id,
|
|
105
|
+
name: opts.name,
|
|
106
|
+
description: opts.description,
|
|
107
|
+
type: (opts.type ?? 'utility'),
|
|
108
|
+
implementation: opts.implementation ?? '',
|
|
109
|
+
tags: opts.tags ?? [],
|
|
110
|
+
status: 'stable',
|
|
111
|
+
created_at: nowISO(),
|
|
112
|
+
author: opts.author,
|
|
113
|
+
author_id: opts.authorId,
|
|
114
|
+
model: opts.model,
|
|
115
|
+
};
|
|
116
|
+
saveTool(tool, cwd);
|
|
117
|
+
appendEvent({ action: 'create', item_type: 'decision', item_id: tool.id, agent: opts.author, agent_id: opts.authorId, summary: `tool: ${opts.name}` }, cwd);
|
|
118
|
+
return tool;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=registries.js.map
|
package/dist/core/schema.js
CHANGED
|
@@ -42,6 +42,7 @@ export const PrioritySchema = z.enum(['low', 'medium', 'high']);
|
|
|
42
42
|
export const MemoryVisibilitySchema = z.enum(['shared', 'machine', 'private']);
|
|
43
43
|
export const HandoffStatusSchema = z.enum(['open', 'accepted', 'closed']);
|
|
44
44
|
export const DecisionOutcomeSchema = z.enum(['approved', 'rejected', 'deferred', 'pending']);
|
|
45
|
+
export const MemoryScopeSchema = z.enum(['project', 'machine', 'user']).default('project');
|
|
45
46
|
export const ConstraintSchema = z.object({
|
|
46
47
|
schema_version: z.number().int().positive().optional(),
|
|
47
48
|
id: z.string(),
|
|
@@ -56,6 +57,7 @@ export const ConstraintSchema = z.object({
|
|
|
56
57
|
session_id: z.string().optional(),
|
|
57
58
|
status: ConstraintStatusSchema,
|
|
58
59
|
category: ConstraintCategorySchema.optional(),
|
|
60
|
+
scope: MemoryScopeSchema.optional(),
|
|
59
61
|
tags: z.array(z.string()),
|
|
60
62
|
related_paths: z.array(z.string()).optional(),
|
|
61
63
|
expires_at: z.string().optional(),
|
|
@@ -73,6 +75,7 @@ export const DecisionSchema = z.object({
|
|
|
73
75
|
host_id: z.string().optional(),
|
|
74
76
|
session_id: z.string().optional(),
|
|
75
77
|
outcome: DecisionOutcomeSchema.optional(),
|
|
78
|
+
scope: MemoryScopeSchema.optional(),
|
|
76
79
|
related_paths: z.array(z.string()).optional(),
|
|
77
80
|
plan_id: z.string().optional(),
|
|
78
81
|
tags: z.array(z.string()),
|
|
@@ -90,6 +93,7 @@ export const TrapSchema = z.object({
|
|
|
90
93
|
session_id: z.string().optional(),
|
|
91
94
|
status: TrapStatusSchema.default('active'),
|
|
92
95
|
severity: SeveritySchema,
|
|
96
|
+
scope: MemoryScopeSchema.optional(),
|
|
93
97
|
tags: z.array(z.string()),
|
|
94
98
|
related_paths: z.array(z.string()).optional(),
|
|
95
99
|
plan_id: z.string().optional(),
|
|
@@ -122,10 +126,11 @@ export const HandoffSchema = z.object({
|
|
|
122
126
|
}).optional(),
|
|
123
127
|
});
|
|
124
128
|
export const PlanStatusSchema = z.enum(['todo', 'in_progress', 'blocked', 'done', 'dropped']);
|
|
129
|
+
export const PlanStepStatusSchema = z.enum(['todo', 'in_progress', 'testing', 'done', 'blocked']);
|
|
125
130
|
export const PlanStepSchema = z.object({
|
|
126
131
|
id: z.string(),
|
|
127
132
|
text: z.string(),
|
|
128
|
-
status:
|
|
133
|
+
status: PlanStepStatusSchema.default('todo'),
|
|
129
134
|
assignee: z.string().optional(),
|
|
130
135
|
created_at: z.string(),
|
|
131
136
|
updated_at: z.string(),
|
|
@@ -413,7 +418,7 @@ export const ProjectModeSchema = z.enum(['single-project', 'multi-project', 'aut
|
|
|
413
418
|
export const ProjectStrategySchema = z.enum(['manual', 'folder']);
|
|
414
419
|
export const TopologyModeSchema = z.enum(['embedded', 'sidecar', 'local-only']);
|
|
415
420
|
export const IgnoreStrategySchema = z.enum(['project-gitignore', 'none']);
|
|
416
|
-
export const AgentKindSchema = z.enum(['agent', 'human', 'unknown']);
|
|
421
|
+
export const AgentKindSchema = z.enum(['agent', 'autonomous', 'human', 'unknown']);
|
|
417
422
|
export const AgentTrustLevelSchema = z.enum(['observer', 'contributor', 'trusted', 'curator']);
|
|
418
423
|
export const AgentIdentityKeySchema = z.object({
|
|
419
424
|
algorithm: z.literal('ed25519'),
|
|
@@ -633,6 +638,10 @@ export const AgentIntegrationNameSchema = z.enum([
|
|
|
633
638
|
'continue',
|
|
634
639
|
'roo',
|
|
635
640
|
'openclaw',
|
|
641
|
+
'nanoclaw',
|
|
642
|
+
'nemoclaw',
|
|
643
|
+
'picoclaw',
|
|
644
|
+
'zeroclaw',
|
|
636
645
|
]);
|
|
637
646
|
export const AgentIntegrationSurfaceKindSchema = z.enum(['instructions', 'mcp', 'skill', 'rule', 'hook']);
|
|
638
647
|
export const AgentIntegrationLocationSchema = z.enum(['workspace', 'machine']);
|
|
@@ -44,14 +44,21 @@ More directive:
|
|
|
44
44
|
- The top 5 most critical traps (the agent won't see them otherwise)
|
|
45
45
|
- Explicit step-by-step protocol with all MCP calls listed
|
|
46
46
|
|
|
47
|
-
### For agents without MCP (Copilot)
|
|
47
|
+
### For agents without MCP (Copilot, autonomous agents)
|
|
48
48
|
|
|
49
|
-
Full static context:
|
|
49
|
+
Full static context via instruction file or SKILL.md:
|
|
50
50
|
- All of the above
|
|
51
51
|
- Active plans with status and assignees
|
|
52
52
|
- All shared traps
|
|
53
53
|
- Recent architectural decisions
|
|
54
54
|
|
|
55
|
+
### For autonomous agents (OpenClaw, NanoClaw, NemoClaw, PicoClaw, ZeroClaw)
|
|
56
|
+
|
|
57
|
+
Skill-based integration via `skills/<agent>/SKILL.md`:
|
|
58
|
+
- Compact brainclaw usage instructions adapted to the agent's workflow
|
|
59
|
+
- Uses `--profile compact` by default (short sessions, constrained resources)
|
|
60
|
+
- Supports task-based and scheduled workflow models
|
|
61
|
+
|
|
55
62
|
## Setting up agent integration
|
|
56
63
|
|
|
57
64
|
### Automatic (recommended)
|
|
@@ -83,7 +90,7 @@ brainclaw export --detect --write # auto-detect and write all formats
|
|
|
83
90
|
When brainclaw memory changes (new constraints, resolved traps, updated plans), regenerate instruction files:
|
|
84
91
|
|
|
85
92
|
```bash
|
|
86
|
-
brainclaw export --all # all
|
|
93
|
+
brainclaw export --all # all 15 agent formats at once
|
|
87
94
|
brainclaw export --detect --write # only the detected agent
|
|
88
95
|
```
|
|
89
96
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.28.0",
|
|
4
4
|
"description": "Shared project memory for humans and coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,12 @@
|
|
|
13
13
|
"README.md",
|
|
14
14
|
"LICENSE"
|
|
15
15
|
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18.0.0"
|
|
21
|
+
},
|
|
16
22
|
"scripts": {
|
|
17
23
|
"build": "tsc",
|
|
18
24
|
"dev": "tsc && node dist/cli.js",
|