brainclaw 0.19.6 → 0.19.10
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 +225 -126
- package/dist/cli.js +8 -3
- package/dist/commands/accept.js +102 -104
- package/dist/commands/add-step.js +3 -5
- package/dist/commands/bootstrap.js +72 -3
- package/dist/commands/capability.js +3 -5
- package/dist/commands/claim.js +14 -12
- package/dist/commands/complete-step.js +3 -5
- package/dist/commands/constraint.js +3 -5
- package/dist/commands/decision.js +3 -6
- package/dist/commands/delete-plan.js +3 -5
- package/dist/commands/handoff.js +3 -5
- package/dist/commands/init.js +20 -0
- package/dist/commands/instruction.js +16 -9
- package/dist/commands/mcp.js +18 -22
- package/dist/commands/memory.js +4 -7
- package/dist/commands/plan.js +3 -5
- package/dist/commands/prune.js +27 -25
- package/dist/commands/reflect.js +3 -5
- package/dist/commands/release-claim.js +23 -20
- package/dist/commands/release-claims.js +22 -21
- package/dist/commands/rollback.js +2 -2
- package/dist/commands/tool.js +3 -5
- package/dist/commands/trap.js +3 -5
- package/dist/commands/update-handoff.js +3 -5
- package/dist/commands/update-plan.js +3 -5
- package/dist/commands/upgrade.js +2 -2
- package/dist/core/audit.js +25 -25
- package/dist/core/bootstrap.js +587 -4
- package/dist/core/candidates.js +10 -6
- package/dist/core/claims.js +10 -8
- package/dist/core/coordination.js +2 -2
- package/dist/core/instructions.js +4 -2
- package/dist/core/io.js +8 -0
- package/dist/core/lock.js +18 -2
- package/dist/core/migration.js +6 -2
- package/dist/core/runtime.js +18 -14
- package/dist/core/schema.js +69 -0
- package/dist/core/state.js +21 -4
- package/docs/cli.md +21 -1
- package/docs/integrations/agents.md +42 -29
- package/docs/integrations/claude-code.md +4 -4
- package/docs/integrations/codex.md +5 -5
- package/docs/integrations/copilot.md +3 -2
- package/docs/integrations/cursor.md +4 -4
- package/docs/integrations/mcp.md +53 -24
- package/docs/integrations/overview.md +53 -40
- package/docs/mcp-schema-changelog.md +3 -0
- package/docs/product/positioning.md +17 -18
- package/docs/quickstart.md +87 -55
- package/package.json +1 -2
package/dist/commands/accept.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { memoryExists,
|
|
1
|
+
import { memoryExists, withStoreLock } from '../core/io.js';
|
|
2
2
|
import { loadCandidate, archiveCandidate, resolveIdOrAlias } from '../core/candidates.js';
|
|
3
|
-
import { loadState,
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
3
|
+
import { loadState, persistState } from '../core/state.js';
|
|
5
4
|
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
6
5
|
import { generateTrapIdWithLabel } from '../core/traps.js';
|
|
7
6
|
import { requireMinimumTrustLevel, requireRegisteredAgentIdentity } from '../core/agent-registry.js';
|
|
@@ -36,109 +35,108 @@ export function acceptCandidate(id, by, cwd, byId) {
|
|
|
36
35
|
});
|
|
37
36
|
requireMinimumTrustLevel(actorIdentity, 'trusted');
|
|
38
37
|
const actor = actorIdentity.agent_name;
|
|
39
|
-
const state = loadState(cwd);
|
|
40
38
|
let promotedItemId = '';
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
39
|
+
withStoreLock(cwd, () => {
|
|
40
|
+
const state = loadState(cwd);
|
|
41
|
+
switch (candidate.type) {
|
|
42
|
+
case 'constraint': {
|
|
43
|
+
const { id: entryId, short_label } = generateIdWithLabel('active_constraints', cwd);
|
|
44
|
+
const entry = {
|
|
45
|
+
id: entryId,
|
|
46
|
+
short_label,
|
|
47
|
+
text: candidate.text,
|
|
48
|
+
created_at: candidate.created_at,
|
|
49
|
+
author: candidate.author,
|
|
50
|
+
author_id: candidate.author_id,
|
|
51
|
+
project_id: candidate.project_id,
|
|
52
|
+
host_id: candidate.host_id,
|
|
53
|
+
session_id: candidate.session_id,
|
|
54
|
+
status: 'active',
|
|
55
|
+
tags: candidate.tags,
|
|
56
|
+
};
|
|
57
|
+
state.active_constraints.push(entry);
|
|
58
|
+
promotedItemId = entryId;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case 'decision': {
|
|
62
|
+
const { id: entryId, short_label } = generateIdWithLabel('recent_decisions', cwd);
|
|
63
|
+
const entry = {
|
|
64
|
+
id: entryId,
|
|
65
|
+
short_label,
|
|
66
|
+
text: candidate.text,
|
|
67
|
+
created_at: candidate.created_at,
|
|
68
|
+
author: candidate.author,
|
|
69
|
+
author_id: candidate.author_id,
|
|
70
|
+
project_id: candidate.project_id,
|
|
71
|
+
host_id: candidate.host_id,
|
|
72
|
+
session_id: candidate.session_id,
|
|
73
|
+
related_paths: candidate.related_paths,
|
|
74
|
+
plan_id: candidate.plan_id,
|
|
75
|
+
tags: candidate.tags,
|
|
76
|
+
};
|
|
77
|
+
state.recent_decisions.push(entry);
|
|
78
|
+
promotedItemId = entryId;
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
case 'trap': {
|
|
82
|
+
const { id: entryId, short_label } = generateTrapIdWithLabel(cwd);
|
|
83
|
+
const entry = {
|
|
84
|
+
id: entryId,
|
|
85
|
+
short_label,
|
|
86
|
+
text: candidate.text,
|
|
87
|
+
created_at: candidate.created_at,
|
|
88
|
+
author: candidate.author,
|
|
89
|
+
author_id: candidate.author_id,
|
|
90
|
+
project_id: candidate.project_id,
|
|
91
|
+
host_id: candidate.host_id,
|
|
92
|
+
session_id: candidate.session_id,
|
|
93
|
+
status: 'active',
|
|
94
|
+
severity: candidate.severity ?? 'medium',
|
|
95
|
+
tags: candidate.tags,
|
|
96
|
+
plan_id: candidate.plan_id,
|
|
97
|
+
visibility: 'shared',
|
|
98
|
+
};
|
|
99
|
+
state.known_traps.push(entry);
|
|
100
|
+
promotedItemId = entryId;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
case 'handoff': {
|
|
104
|
+
const { id: entryId, short_label } = generateIdWithLabel('open_handoffs', cwd);
|
|
105
|
+
const entry = {
|
|
106
|
+
id: entryId,
|
|
107
|
+
short_label,
|
|
108
|
+
from: candidate.from ?? 'unknown',
|
|
109
|
+
to: candidate.to ?? 'unknown',
|
|
110
|
+
text: candidate.text,
|
|
111
|
+
created_at: candidate.created_at,
|
|
112
|
+
author: candidate.author,
|
|
113
|
+
author_id: candidate.author_id,
|
|
114
|
+
project_id: candidate.project_id,
|
|
115
|
+
host_id: candidate.host_id,
|
|
116
|
+
session_id: candidate.session_id,
|
|
117
|
+
status: 'open',
|
|
118
|
+
tags: candidate.tags,
|
|
119
|
+
};
|
|
120
|
+
state.open_handoffs.push(entry);
|
|
121
|
+
promotedItemId = entryId;
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
61
124
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
state.recent_decisions.push(entry);
|
|
79
|
-
promotedItemId = entryId;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
case 'trap': {
|
|
83
|
-
const { id: entryId, short_label } = generateTrapIdWithLabel(cwd);
|
|
84
|
-
const entry = {
|
|
85
|
-
id: entryId,
|
|
86
|
-
short_label,
|
|
87
|
-
text: candidate.text,
|
|
88
|
-
created_at: candidate.created_at,
|
|
89
|
-
author: candidate.author,
|
|
90
|
-
author_id: candidate.author_id,
|
|
91
|
-
project_id: candidate.project_id,
|
|
92
|
-
host_id: candidate.host_id,
|
|
93
|
-
session_id: candidate.session_id,
|
|
94
|
-
status: 'active',
|
|
95
|
-
severity: candidate.severity ?? 'medium',
|
|
96
|
-
tags: candidate.tags,
|
|
97
|
-
plan_id: candidate.plan_id,
|
|
98
|
-
visibility: 'shared',
|
|
99
|
-
};
|
|
100
|
-
state.known_traps.push(entry);
|
|
101
|
-
promotedItemId = entryId;
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
case 'handoff': {
|
|
105
|
-
const { id: entryId, short_label } = generateIdWithLabel('open_handoffs', cwd);
|
|
106
|
-
const entry = {
|
|
107
|
-
id: entryId,
|
|
108
|
-
short_label,
|
|
109
|
-
from: candidate.from ?? 'unknown',
|
|
110
|
-
to: candidate.to ?? 'unknown',
|
|
111
|
-
text: candidate.text,
|
|
112
|
-
created_at: candidate.created_at,
|
|
113
|
-
author: candidate.author,
|
|
114
|
-
author_id: candidate.author_id,
|
|
115
|
-
project_id: candidate.project_id,
|
|
116
|
-
host_id: candidate.host_id,
|
|
117
|
-
session_id: candidate.session_id,
|
|
118
|
-
status: 'open',
|
|
119
|
-
tags: candidate.tags,
|
|
120
|
-
};
|
|
121
|
-
state.open_handoffs.push(entry);
|
|
122
|
-
promotedItemId = entryId;
|
|
123
|
-
break;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
saveState(state, cwd);
|
|
127
|
-
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(state, cwd));
|
|
128
|
-
// Archive candidate (use resolved hash ID)
|
|
129
|
-
candidate.status = 'accepted';
|
|
130
|
-
candidate.resolved_at = nowISO();
|
|
131
|
-
candidate.resolved_by = actor;
|
|
132
|
-
archiveCandidate(candidate, 'accepted', cwd);
|
|
133
|
-
appendAuditEntry({
|
|
134
|
-
actor,
|
|
135
|
-
actor_id: actorIdentity.agent_id,
|
|
136
|
-
action: 'accept',
|
|
137
|
-
item_id: resolvedId,
|
|
138
|
-
item_type: candidate.type,
|
|
139
|
-
after: { type: candidate.type, text: candidate.text },
|
|
140
|
-
reason: 'trusted-agent',
|
|
141
|
-
}, cwd);
|
|
125
|
+
persistState(state, cwd);
|
|
126
|
+
candidate.status = 'accepted';
|
|
127
|
+
candidate.resolved_at = nowISO();
|
|
128
|
+
candidate.resolved_by = actor;
|
|
129
|
+
archiveCandidate(candidate, 'accepted', cwd);
|
|
130
|
+
appendAuditEntry({
|
|
131
|
+
actor,
|
|
132
|
+
actor_id: actorIdentity.agent_id,
|
|
133
|
+
action: 'accept',
|
|
134
|
+
item_id: resolvedId,
|
|
135
|
+
item_type: candidate.type,
|
|
136
|
+
after: { type: candidate.type, text: candidate.text },
|
|
137
|
+
reason: 'trusted-agent',
|
|
138
|
+
}, cwd);
|
|
139
|
+
});
|
|
142
140
|
return {
|
|
143
141
|
candidate_id: resolvedId,
|
|
144
142
|
candidate_type: candidate.type,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { loadState,
|
|
2
|
-
import { memoryExists
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
|
+
import { memoryExists } from '../core/io.js';
|
|
3
3
|
import { generateId, nowISO } from '../core/ids.js';
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
5
4
|
import { validateCliInput } from '../core/input-validation.js';
|
|
6
5
|
export function runAddStep(planId, text, options = {}) {
|
|
7
6
|
if (!memoryExists()) {
|
|
@@ -25,8 +24,7 @@ export function runAddStep(planId, text, options = {}) {
|
|
|
25
24
|
};
|
|
26
25
|
plan.steps = [...(plan.steps ?? []), step];
|
|
27
26
|
plan.updated_at = nowISO();
|
|
28
|
-
|
|
29
|
-
writeFileAtomic(memoryPath('project.md'), generateMarkdown(state));
|
|
27
|
+
persistState(state);
|
|
30
28
|
const total = plan.steps.length;
|
|
31
29
|
const done = plan.steps.filter((s) => s.status === 'done').length;
|
|
32
30
|
console.log(`✔ Step added: [${step.id}] ${text}`);
|
|
@@ -1,12 +1,42 @@
|
|
|
1
|
+
import readline from 'node:readline/promises';
|
|
2
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
1
3
|
import { memoryExists } from '../core/io.js';
|
|
2
|
-
import { renderBootstrapSummary, runBootstrapProfile } from '../core/bootstrap.js';
|
|
3
|
-
export function runBootstrap(options = {}) {
|
|
4
|
+
import { applyBootstrapImport, renderBootstrapInterview, renderBootstrapSummary, runBootstrapProfile, uninstallBootstrapImport, } from '../core/bootstrap.js';
|
|
5
|
+
export async function runBootstrap(options = {}) {
|
|
4
6
|
const cwd = options.cwd ?? process.cwd();
|
|
5
7
|
if (!memoryExists(cwd)) {
|
|
6
8
|
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
7
9
|
process.exit(1);
|
|
8
10
|
}
|
|
9
11
|
try {
|
|
12
|
+
if (options.apply && options.uninstall) {
|
|
13
|
+
console.error('Error: --apply and --uninstall are mutually exclusive.');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const audience = resolveBootstrapInterviewAudience(options.audience);
|
|
17
|
+
if (options.uninstall) {
|
|
18
|
+
await confirmBootstrapAction('Remove the last bootstrap import?', options.yes);
|
|
19
|
+
const result = uninstallBootstrapImport(cwd);
|
|
20
|
+
if (!result.receipt) {
|
|
21
|
+
console.log('No bootstrap import receipt found.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
console.log(`✔ Bootstrap uninstall completed: ${result.deactivatedCount} instruction(s) deactivated, ${result.skippedCount} artifact(s) skipped.`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (options.apply) {
|
|
28
|
+
await confirmBootstrapAction('Apply the current bootstrap import proposal to canonical memory?', options.yes);
|
|
29
|
+
const result = applyBootstrapImport({
|
|
30
|
+
target: options.for,
|
|
31
|
+
refresh: options.refresh,
|
|
32
|
+
cwd,
|
|
33
|
+
});
|
|
34
|
+
console.log(`✔ Bootstrap import applied: ${result.createdCount} item(s) created, ${result.skippedCount} suggestion(s) skipped.`);
|
|
35
|
+
if (result.receipt) {
|
|
36
|
+
console.log(`✔ Receipt saved: ${result.receipt.managed_artifacts.length} managed artifact(s) can be reverted with \`brainclaw bootstrap --uninstall\`.`);
|
|
37
|
+
}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
10
40
|
const result = runBootstrapProfile({
|
|
11
41
|
target: options.for,
|
|
12
42
|
refresh: options.refresh,
|
|
@@ -18,17 +48,56 @@ export function runBootstrap(options = {}) {
|
|
|
18
48
|
target: result.profile.target,
|
|
19
49
|
repo_fingerprint: result.profile.repo_fingerprint,
|
|
20
50
|
sources_scanned: result.profile.sources_scanned,
|
|
51
|
+
workspace_kind: result.profile.workspace_kind,
|
|
52
|
+
confidence: result.profile.confidence,
|
|
53
|
+
native_instruction_files: result.profile.native_instruction_files,
|
|
54
|
+
gaps: result.profile.gaps,
|
|
21
55
|
seed_count: result.profile.seed_count,
|
|
22
56
|
seeds: result.seeds,
|
|
57
|
+
import_plan: result.importPlan,
|
|
58
|
+
last_application: result.lastApplication,
|
|
23
59
|
reused_profile: result.reusedProfile,
|
|
24
60
|
}, null, 2));
|
|
25
61
|
return;
|
|
26
62
|
}
|
|
27
|
-
console.log(renderBootstrapSummary(result));
|
|
63
|
+
console.log(options.interview ? renderBootstrapInterview(result, audience) : renderBootstrapSummary(result));
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function resolveBootstrapInterviewAudience(value) {
|
|
71
|
+
if (!value) {
|
|
72
|
+
return 'any';
|
|
73
|
+
}
|
|
74
|
+
if (value === 'cli' || value === 'ide_chat' || value === 'any') {
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`Unsupported bootstrap interview audience '${value}'. Use cli, ide_chat, or any.`);
|
|
78
|
+
}
|
|
79
|
+
async function confirmBootstrapAction(question, yes) {
|
|
80
|
+
if (yes) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
84
|
+
console.error(`Error: ${question} Re-run with --yes in non-interactive mode.`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
const rl = readline.createInterface({ input, output });
|
|
88
|
+
try {
|
|
89
|
+
const answer = await rl.question(`${question} [y/N] `);
|
|
90
|
+
if (answer.trim().toLowerCase() !== 'y') {
|
|
91
|
+
console.error('Cancelled.');
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
28
94
|
}
|
|
29
95
|
catch (error) {
|
|
30
96
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
31
97
|
process.exit(1);
|
|
32
98
|
}
|
|
99
|
+
finally {
|
|
100
|
+
rl.close();
|
|
101
|
+
}
|
|
33
102
|
}
|
|
34
103
|
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { loadState,
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
2
|
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
3
|
-
import { memoryExists
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
3
|
+
import { memoryExists } from '../core/io.js';
|
|
5
4
|
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
6
5
|
import { loadConfig } from '../core/config.js';
|
|
7
6
|
import { scanText } from '../core/security.js';
|
|
@@ -80,8 +79,7 @@ function runCapabilityAdd(name, description, options, cwd) {
|
|
|
80
79
|
// For now, store as decision to avoid schema migration
|
|
81
80
|
// Will migrate to separate capability storage in v0.16
|
|
82
81
|
state.recent_decisions.push(entry);
|
|
83
|
-
|
|
84
|
-
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(state));
|
|
82
|
+
persistState(state, cwd);
|
|
85
83
|
console.log(`✔ Capability added: [${id}] ${name}`);
|
|
86
84
|
console.log(' (Stored in decisions for now; will move to dedicated registry in v0.16)');
|
|
87
85
|
}
|
package/dist/commands/claim.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { buildOperationalIdentity } from '../core/identity.js';
|
|
2
|
-
import { memoryExists, memoryPath, writeFileAtomic } from '../core/io.js';
|
|
2
|
+
import { memoryExists, memoryPath, withStoreLock, writeFileAtomic } from '../core/io.js';
|
|
3
3
|
import { saveClaim, generateClaimId, listClaims } from '../core/claims.js';
|
|
4
4
|
import { generateMarkdown } from '../core/markdown.js';
|
|
5
5
|
import { loadState, saveState } from '../core/state.js';
|
|
@@ -72,18 +72,20 @@ export function runClaim(description, options) {
|
|
|
72
72
|
status: 'active',
|
|
73
73
|
expires_at: options.ttl ? parseTtl(options.ttl) : undefined,
|
|
74
74
|
};
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
plan.assignee
|
|
75
|
+
withStoreLock(options.cwd, () => {
|
|
76
|
+
if (plan) {
|
|
77
|
+
if (!plan.assignee) {
|
|
78
|
+
plan.assignee = actor.agent;
|
|
79
|
+
}
|
|
80
|
+
if (plan.status === 'todo') {
|
|
81
|
+
plan.status = 'in_progress';
|
|
82
|
+
}
|
|
83
|
+
plan.updated_at = nowISO();
|
|
84
|
+
saveState(state, options.cwd);
|
|
78
85
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
plan.updated_at = nowISO();
|
|
83
|
-
saveState(state, options.cwd);
|
|
84
|
-
}
|
|
85
|
-
saveClaim(claim, options.cwd);
|
|
86
|
-
writeFileAtomic(memoryPath('project.md', options.cwd), generateMarkdown(plan ? state : loadState(options.cwd), options.cwd));
|
|
86
|
+
saveClaim(claim, options.cwd);
|
|
87
|
+
writeFileAtomic(memoryPath('project.md', options.cwd), generateMarkdown(plan ? state : loadState(options.cwd), options.cwd));
|
|
88
|
+
});
|
|
87
89
|
const planInfo = claim.plan_id ? ` [plan ${claim.plan_id}]` : '';
|
|
88
90
|
const ttlInfo = claim.expires_at ? ` (expires ${claim.expires_at.slice(0, 16).replace('T', ' ')})` : '';
|
|
89
91
|
const storeLabel = options.store && options.store !== 'local' ? ` [store:${options.store}]` : '';
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { loadState,
|
|
2
|
-
import { memoryExists
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
|
+
import { memoryExists } from '../core/io.js';
|
|
3
3
|
import { nowISO } from '../core/ids.js';
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
5
4
|
export function runCompleteStep(planId, stepId) {
|
|
6
5
|
if (!memoryExists()) {
|
|
7
6
|
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
@@ -21,8 +20,7 @@ export function runCompleteStep(planId, stepId) {
|
|
|
21
20
|
step.status = 'done';
|
|
22
21
|
step.updated_at = nowISO();
|
|
23
22
|
plan.updated_at = nowISO();
|
|
24
|
-
|
|
25
|
-
writeFileAtomic(memoryPath('project.md'), generateMarkdown(state));
|
|
23
|
+
persistState(state);
|
|
26
24
|
const total = plan.steps.length;
|
|
27
25
|
const done = plan.steps.filter((s) => s.status === 'done').length;
|
|
28
26
|
console.log(`✔ Step completed: [${step.id}] ${step.text}`);
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { loadState,
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
2
|
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
3
3
|
import { loadConfig } from '../core/config.js';
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
5
4
|
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
6
5
|
import { scanText } from '../core/security.js';
|
|
7
|
-
import { memoryExists
|
|
6
|
+
import { memoryExists } from '../core/io.js';
|
|
8
7
|
import { validateCliInput } from '../core/input-validation.js';
|
|
9
8
|
import { resolveTargetStore } from '../core/store-resolution.js';
|
|
10
9
|
export function runConstraint(text, options = {}) {
|
|
@@ -37,8 +36,7 @@ export function runConstraint(text, options = {}) {
|
|
|
37
36
|
related_paths: options.path,
|
|
38
37
|
};
|
|
39
38
|
state.active_constraints.push(entry);
|
|
40
|
-
|
|
41
|
-
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(state));
|
|
39
|
+
persistState(state, cwd);
|
|
42
40
|
console.log(`✔ Constraint added: [${id}] ${text}`);
|
|
43
41
|
}
|
|
44
42
|
//# sourceMappingURL=constraint.js.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { loadState,
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
2
|
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
3
3
|
import { loadConfig } from '../core/config.js';
|
|
4
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
5
4
|
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
6
5
|
import { scanText } from '../core/security.js';
|
|
7
|
-
import { memoryExists
|
|
6
|
+
import { memoryExists } from '../core/io.js';
|
|
8
7
|
import { validateCliInput } from '../core/input-validation.js';
|
|
9
8
|
import { resolveTargetStore } from '../core/store-resolution.js';
|
|
10
9
|
export function runDecision(text, options = {}) {
|
|
@@ -37,9 +36,7 @@ export function runDecision(text, options = {}) {
|
|
|
37
36
|
plan_id: options.plan,
|
|
38
37
|
};
|
|
39
38
|
state.recent_decisions.push(entry);
|
|
40
|
-
|
|
41
|
-
// Rebuild markdown
|
|
42
|
-
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(state));
|
|
39
|
+
persistState(state, cwd);
|
|
43
40
|
console.log(`✔ Decision added: [${id}] ${text}`);
|
|
44
41
|
}
|
|
45
42
|
//# sourceMappingURL=decision.js.map
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { loadState,
|
|
2
|
-
import { memoryExists
|
|
3
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
1
|
+
import { loadState, persistState } from '../core/state.js';
|
|
2
|
+
import { memoryExists } from '../core/io.js';
|
|
4
3
|
export function runDeletePlan(id, options = {}) {
|
|
5
4
|
if (!memoryExists(options.cwd)) {
|
|
6
5
|
console.error('Error: .brainclaw/ not found. Run `brainclaw init` first.');
|
|
@@ -13,8 +12,7 @@ export function runDeletePlan(id, options = {}) {
|
|
|
13
12
|
process.exit(1);
|
|
14
13
|
}
|
|
15
14
|
const [plan] = state.plan_items.splice(index, 1);
|
|
16
|
-
|
|
17
|
-
writeFileAtomic(memoryPath('project.md', options.cwd), generateMarkdown(state, options.cwd));
|
|
15
|
+
persistState(state, options.cwd);
|
|
18
16
|
console.log(`✔ Plan item deleted: [${plan.id}] ${plan.text}`);
|
|
19
17
|
}
|
|
20
18
|
//# sourceMappingURL=delete-plan.js.map
|
package/dist/commands/handoff.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
-
import { loadState,
|
|
2
|
+
import { loadState, persistState } from '../core/state.js';
|
|
3
3
|
import { resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
4
4
|
import { loadConfig } from '../core/config.js';
|
|
5
|
-
import { generateMarkdown } from '../core/markdown.js';
|
|
6
5
|
import { generateIdWithLabel, nowISO } from '../core/ids.js';
|
|
7
6
|
import { scanText } from '../core/security.js';
|
|
8
|
-
import { memoryExists
|
|
7
|
+
import { memoryExists } from '../core/io.js';
|
|
9
8
|
import { validateCliInput } from '../core/input-validation.js';
|
|
10
9
|
import { resolveTargetStore } from '../core/store-resolution.js';
|
|
11
10
|
export function runHandoff(text, options) {
|
|
@@ -56,8 +55,7 @@ export function runHandoff(text, options) {
|
|
|
56
55
|
snapshot: diff ? { diff } : undefined,
|
|
57
56
|
};
|
|
58
57
|
state.open_handoffs.push(entry);
|
|
59
|
-
|
|
60
|
-
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(state, cwd));
|
|
58
|
+
persistState(state, cwd);
|
|
61
59
|
console.log(`✔ Handoff added: [${id}] ${options.from} → ${options.to}: ${text}`);
|
|
62
60
|
}
|
|
63
61
|
//# sourceMappingURL=handoff.js.map
|
package/dist/commands/init.js
CHANGED
|
@@ -10,6 +10,7 @@ import { initMemoryRepo } from '../core/memory-git.js';
|
|
|
10
10
|
import { buildProjectIdentity, resolveExistingProjectIdentity, saveProjectIdentity } from '../core/project-registry.js';
|
|
11
11
|
import { scanProject, upsertProject } from '../core/global-registry.js';
|
|
12
12
|
import { analyzeRepository, scanWorkspaceBoundaries } from '../core/repo-analysis.js';
|
|
13
|
+
import { renderBootstrapSummary, runBootstrapProfile } from '../core/bootstrap.js';
|
|
13
14
|
import { isAgentIntegrationName, upsertAgentIntegrationDeclaration } from '../core/agent-integrations.js';
|
|
14
15
|
import { describeAutoConfigWrite, ensureAgentFiles, ensureGitignoreEntries, writeDetectedAgentAutoConfig } from '../core/agent-files.js';
|
|
15
16
|
import { detectAiAgent, detectWslEnvironment } from '../core/ai-agent-detection.js';
|
|
@@ -228,6 +229,25 @@ export async function runInit(options = {}) {
|
|
|
228
229
|
if (initMemoryRepo(cwd)) {
|
|
229
230
|
console.log('✔ Initialized memory git repo for versioning');
|
|
230
231
|
}
|
|
232
|
+
const onboardingPreflight = runBootstrapProfile({ cwd, refresh: true });
|
|
233
|
+
console.log('');
|
|
234
|
+
console.log('Onboarding preflight:');
|
|
235
|
+
for (const line of renderBootstrapSummary(onboardingPreflight).split('\n')) {
|
|
236
|
+
console.log(` ${line}`);
|
|
237
|
+
}
|
|
238
|
+
if (onboardingPreflight.importPlan.suggestion_count > 0) {
|
|
239
|
+
console.log('');
|
|
240
|
+
console.log(`Next step: run 'brainclaw bootstrap --apply' to import ${onboardingPreflight.importPlan.suggestion_count} suggested item(s) into canonical memory.`);
|
|
241
|
+
console.log(`Rollback: run 'brainclaw bootstrap --uninstall' to deactivate the last bootstrap-managed import.`);
|
|
242
|
+
}
|
|
243
|
+
if ((onboardingPreflight.importPlan.interview?.question_count ?? 0) > 0) {
|
|
244
|
+
console.log('');
|
|
245
|
+
console.log(`Interview: run 'brainclaw bootstrap --interview --audience cli' for terminal agents or '--audience ide_chat' for IDE chat agents.`);
|
|
246
|
+
}
|
|
247
|
+
else if ((onboardingPreflight.profile.gaps?.length ?? 0) > 0) {
|
|
248
|
+
console.log('');
|
|
249
|
+
console.log(`Next step: review the onboarding gaps, then use 'brainclaw bootstrap --json' as the basis for an interview/import flow.`);
|
|
250
|
+
}
|
|
231
251
|
console.log('');
|
|
232
252
|
console.log(`Tip: run 'brainclaw context --json' to load the shared memory into your agent session.`);
|
|
233
253
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { resolveAgentScope, resolveCurrentAgentName } from '../core/agent-registry.js';
|
|
2
2
|
import { loadConfig } from '../core/config.js';
|
|
3
3
|
import { createInstruction } from '../core/instructions.js';
|
|
4
|
-
import { memoryExists, memoryPath, writeFileAtomic } from '../core/io.js';
|
|
4
|
+
import { memoryExists, memoryPath, withStoreLock, writeFileAtomic } from '../core/io.js';
|
|
5
5
|
import { generateMarkdown } from '../core/markdown.js';
|
|
6
6
|
import { loadState } from '../core/state.js';
|
|
7
7
|
import { scanText } from '../core/security.js';
|
|
@@ -25,14 +25,21 @@ export function runInstruction(text, options = {}) {
|
|
|
25
25
|
process.exit(1);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
28
|
+
let entry;
|
|
29
|
+
withStoreLock(cwd, () => {
|
|
30
|
+
entry = createInstruction(text, {
|
|
31
|
+
layer,
|
|
32
|
+
scope,
|
|
33
|
+
tags: options.tag,
|
|
34
|
+
author: options.author ?? resolveCurrentAgentName(cwd),
|
|
35
|
+
supersedes: options.supersedes,
|
|
36
|
+
}, cwd);
|
|
37
|
+
writeFileAtomic(memoryPath('project.md', cwd), generateMarkdown(loadState(cwd)));
|
|
38
|
+
});
|
|
39
|
+
if (!entry) {
|
|
40
|
+
console.error('Error: failed to persist instruction.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
36
43
|
console.log(`✔ Instruction added: [${entry.id}] <${entry.layer}${entry.scope ? `:${entry.scope}` : ''}> ${entry.text}`);
|
|
37
44
|
}
|
|
38
45
|
function resolveScope(layer, options, cwd) {
|