@theihtisham/agent-shadow-brain 6.0.0 → 6.0.2
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 +107 -7
- package/dist/brain/brain-3d.d.ts +79 -0
- package/dist/brain/brain-3d.d.ts.map +1 -0
- package/dist/brain/brain-3d.js +468 -0
- package/dist/brain/brain-3d.js.map +1 -0
- package/dist/brain/brain-active-learner.d.ts +74 -0
- package/dist/brain/brain-active-learner.d.ts.map +1 -0
- package/dist/brain/brain-active-learner.js +425 -0
- package/dist/brain/brain-active-learner.js.map +1 -0
- package/dist/brain/brain-ascii.d.ts +32 -0
- package/dist/brain/brain-ascii.d.ts.map +1 -0
- package/dist/brain/brain-ascii.js +402 -0
- package/dist/brain/brain-ascii.js.map +1 -0
- package/dist/brain/brain-cinema.d.ts +45 -0
- package/dist/brain/brain-cinema.d.ts.map +1 -0
- package/dist/brain/brain-cinema.js +393 -0
- package/dist/brain/brain-cinema.js.map +1 -0
- package/dist/brain/brain-coach.d.ts +45 -0
- package/dist/brain/brain-coach.d.ts.map +1 -0
- package/dist/brain/brain-coach.js +383 -0
- package/dist/brain/brain-coach.js.map +1 -0
- package/dist/brain/brain-consolidator.d.ts +56 -0
- package/dist/brain/brain-consolidator.d.ts.map +1 -0
- package/dist/brain/brain-consolidator.js +386 -0
- package/dist/brain/brain-consolidator.js.map +1 -0
- package/dist/brain/brain-contradictions.d.ts +57 -0
- package/dist/brain/brain-contradictions.d.ts.map +1 -0
- package/dist/brain/brain-contradictions.js +443 -0
- package/dist/brain/brain-contradictions.js.map +1 -0
- package/dist/brain/brain-diff.d.ts +61 -0
- package/dist/brain/brain-diff.d.ts.map +1 -0
- package/dist/brain/brain-diff.js +439 -0
- package/dist/brain/brain-diff.js.map +1 -0
- package/dist/brain/brain-dna.d.ts +59 -0
- package/dist/brain/brain-dna.d.ts.map +1 -0
- package/dist/brain/brain-dna.js +336 -0
- package/dist/brain/brain-dna.js.map +1 -0
- package/dist/brain/brain-doppelganger.d.ts +32 -0
- package/dist/brain/brain-doppelganger.d.ts.map +1 -0
- package/dist/brain/brain-doppelganger.js +417 -0
- package/dist/brain/brain-doppelganger.js.map +1 -0
- package/dist/brain/brain-graph-walker.d.ts +54 -0
- package/dist/brain/brain-graph-walker.d.ts.map +1 -0
- package/dist/brain/brain-graph-walker.js +412 -0
- package/dist/brain/brain-graph-walker.js.map +1 -0
- package/dist/brain/brain-holiday-card.d.ts +50 -0
- package/dist/brain/brain-holiday-card.d.ts.map +1 -0
- package/dist/brain/brain-holiday-card.js +432 -0
- package/dist/brain/brain-holiday-card.js.map +1 -0
- package/dist/brain/brain-memes.d.ts +44 -0
- package/dist/brain/brain-memes.d.ts.map +1 -0
- package/dist/brain/brain-memes.js +438 -0
- package/dist/brain/brain-memes.js.map +1 -0
- package/dist/brain/brain-memory-tiers.d.ts +67 -0
- package/dist/brain/brain-memory-tiers.d.ts.map +1 -0
- package/dist/brain/brain-memory-tiers.js +292 -0
- package/dist/brain/brain-memory-tiers.js.map +1 -0
- package/dist/brain/brain-notebook.d.ts +68 -0
- package/dist/brain/brain-notebook.d.ts.map +1 -0
- package/dist/brain/brain-notebook.js +379 -0
- package/dist/brain/brain-notebook.js.map +1 -0
- package/dist/brain/brain-quantize.d.ts +62 -0
- package/dist/brain/brain-quantize.d.ts.map +1 -0
- package/dist/brain/brain-quantize.js +346 -0
- package/dist/brain/brain-quantize.js.map +1 -0
- package/dist/brain/brain-query-expander.d.ts +31 -0
- package/dist/brain/brain-query-expander.d.ts.map +1 -0
- package/dist/brain/brain-query-expander.js +417 -0
- package/dist/brain/brain-query-expander.js.map +1 -0
- package/dist/brain/brain-quest.d.ts +58 -0
- package/dist/brain/brain-quest.d.ts.map +1 -0
- package/dist/brain/brain-quest.js +541 -0
- package/dist/brain/brain-quest.js.map +1 -0
- package/dist/brain/brain-recall-cache.d.ts +73 -0
- package/dist/brain/brain-recall-cache.d.ts.map +1 -0
- package/dist/brain/brain-recall-cache.js +444 -0
- package/dist/brain/brain-recall-cache.js.map +1 -0
- package/dist/brain/brain-reflex.d.ts +55 -0
- package/dist/brain/brain-reflex.d.ts.map +1 -0
- package/dist/brain/brain-reflex.js +364 -0
- package/dist/brain/brain-reflex.js.map +1 -0
- package/dist/brain/brain-replay.d.ts +74 -0
- package/dist/brain/brain-replay.d.ts.map +1 -0
- package/dist/brain/brain-replay.js +336 -0
- package/dist/brain/brain-replay.js.map +1 -0
- package/dist/brain/brain-rerank.d.ts +39 -0
- package/dist/brain/brain-rerank.d.ts.map +1 -0
- package/dist/brain/brain-rerank.js +216 -0
- package/dist/brain/brain-rerank.js.map +1 -0
- package/dist/brain/brain-roast.d.ts +44 -0
- package/dist/brain/brain-roast.d.ts.map +1 -0
- package/dist/brain/brain-roast.js +566 -0
- package/dist/brain/brain-roast.js.map +1 -0
- package/dist/brain/brain-sonification.d.ts +57 -0
- package/dist/brain/brain-sonification.d.ts.map +1 -0
- package/dist/brain/brain-sonification.js +286 -0
- package/dist/brain/brain-sonification.js.map +1 -0
- package/dist/brain/brain-tarot.d.ts +49 -0
- package/dist/brain/brain-tarot.d.ts.map +1 -0
- package/dist/brain/brain-tarot.js +634 -0
- package/dist/brain/brain-tarot.js.map +1 -0
- package/dist/brain/brain-time-capsule.d.ts +80 -0
- package/dist/brain/brain-time-capsule.d.ts.map +1 -0
- package/dist/brain/brain-time-capsule.js +289 -0
- package/dist/brain/brain-time-capsule.js.map +1 -0
- package/dist/brain/brain-trophies.d.ts +60 -0
- package/dist/brain/brain-trophies.d.ts.map +1 -0
- package/dist/brain/brain-trophies.js +431 -0
- package/dist/brain/brain-trophies.js.map +1 -0
- package/dist/brain/brain-working-memory.d.ts +78 -0
- package/dist/brain/brain-working-memory.d.ts.map +1 -0
- package/dist/brain/brain-working-memory.js +367 -0
- package/dist/brain/brain-working-memory.js.map +1 -0
- package/dist/brain/confidence-gate.d.ts +69 -0
- package/dist/brain/confidence-gate.d.ts.map +1 -0
- package/dist/brain/confidence-gate.js +244 -0
- package/dist/brain/confidence-gate.js.map +1 -0
- package/dist/brain/constitution.d.ts +59 -0
- package/dist/brain/constitution.d.ts.map +1 -0
- package/dist/brain/constitution.js +315 -0
- package/dist/brain/constitution.js.map +1 -0
- package/dist/brain/embeddings-v2.d.ts +58 -0
- package/dist/brain/embeddings-v2.d.ts.map +1 -0
- package/dist/brain/embeddings-v2.js +344 -0
- package/dist/brain/embeddings-v2.js.map +1 -0
- package/dist/brain/hive-voice.d.ts +71 -0
- package/dist/brain/hive-voice.d.ts.map +1 -0
- package/dist/brain/hive-voice.js +352 -0
- package/dist/brain/hive-voice.js.map +1 -0
- package/dist/brain/markdown-export.d.ts +48 -0
- package/dist/brain/markdown-export.d.ts.map +1 -0
- package/dist/brain/markdown-export.js +382 -0
- package/dist/brain/markdown-export.js.map +1 -0
- package/dist/brain/multimodal-vision.d.ts +38 -0
- package/dist/brain/multimodal-vision.d.ts.map +1 -0
- package/dist/brain/multimodal-vision.js +257 -0
- package/dist/brain/multimodal-vision.js.map +1 -0
- package/dist/brain/otel-lite.d.ts +71 -0
- package/dist/brain/otel-lite.d.ts.map +1 -0
- package/dist/brain/otel-lite.js +232 -0
- package/dist/brain/otel-lite.js.map +1 -0
- package/dist/cli.js +881 -2
- package/dist/cli.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
// src/brain/brain-coach.ts — Proactive idle suggestion engine
|
|
2
|
+
// v6.0.2 — Hive Mind Edition
|
|
3
|
+
//
|
|
4
|
+
// Observes brain activity events and proactively surfaces helpful
|
|
5
|
+
// suggestions when the user goes idle. All detection is heuristic /
|
|
6
|
+
// deterministic — no LLM dependencies. Suggestions are persisted per
|
|
7
|
+
// project under ~/.shadow-brain/coach/<project>.json.
|
|
8
|
+
//
|
|
9
|
+
// Exposed: observe(event), suggestions(project, opts?), dismiss(id),
|
|
10
|
+
// pinned(), pin(id), unpin(id), idleCheck(project, idleSinceMs).
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import * as os from 'os';
|
|
14
|
+
import * as crypto from 'crypto';
|
|
15
|
+
const COACH_DIR = path.join(os.homedir(), '.shadow-brain', 'coach');
|
|
16
|
+
const MAX_EVENTS = 500;
|
|
17
|
+
export class BrainCoach {
|
|
18
|
+
constructor() {
|
|
19
|
+
this.states = new Map();
|
|
20
|
+
this.rules = [];
|
|
21
|
+
this.registerRules();
|
|
22
|
+
}
|
|
23
|
+
/** Feed a brain activity event into the coach. */
|
|
24
|
+
observe(event) {
|
|
25
|
+
const project = event.project || 'default';
|
|
26
|
+
const ts = event.ts ?? Date.now();
|
|
27
|
+
const state = this.loadState(project);
|
|
28
|
+
state.events.push({ ...event, ts, project });
|
|
29
|
+
if (state.events.length > MAX_EVENTS) {
|
|
30
|
+
state.events.splice(0, state.events.length - MAX_EVENTS);
|
|
31
|
+
}
|
|
32
|
+
this.persist(project, state);
|
|
33
|
+
}
|
|
34
|
+
/** Get current suggestions for a project. */
|
|
35
|
+
async suggestions(project, opts = {}) {
|
|
36
|
+
const topN = opts.topN ?? 5;
|
|
37
|
+
const since = opts.sinceMs ?? 0;
|
|
38
|
+
const state = this.loadState(project);
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const rule of this.rules) {
|
|
42
|
+
const s = rule.detect(state.events, project, now);
|
|
43
|
+
if (!s)
|
|
44
|
+
continue;
|
|
45
|
+
if (state.dismissed[s.id])
|
|
46
|
+
continue;
|
|
47
|
+
if (since && (state.surfaced[s.id] || 0) > now - since)
|
|
48
|
+
continue;
|
|
49
|
+
out.push(s);
|
|
50
|
+
}
|
|
51
|
+
out.sort((a, b) => b.priority - a.priority);
|
|
52
|
+
const top = out.slice(0, topN);
|
|
53
|
+
for (const s of top)
|
|
54
|
+
state.surfaced[s.id] = now;
|
|
55
|
+
this.persist(project, state);
|
|
56
|
+
return top;
|
|
57
|
+
}
|
|
58
|
+
/** Mark a suggestion as seen — don't re-surface. */
|
|
59
|
+
dismiss(suggestionId, project = 'default') {
|
|
60
|
+
const state = this.loadState(project);
|
|
61
|
+
state.dismissed[suggestionId] = Date.now();
|
|
62
|
+
this.persist(project, state);
|
|
63
|
+
}
|
|
64
|
+
/** List pinned suggestions across all projects. */
|
|
65
|
+
pinned(project = 'default') {
|
|
66
|
+
const state = this.loadState(project);
|
|
67
|
+
return Object.values(state.pinned);
|
|
68
|
+
}
|
|
69
|
+
pin(id, project = 'default') {
|
|
70
|
+
const state = this.loadState(project);
|
|
71
|
+
// Look in current rule outputs to find the suggestion
|
|
72
|
+
for (const rule of this.rules) {
|
|
73
|
+
const s = rule.detect(state.events, project, Date.now());
|
|
74
|
+
if (s && s.id === id) {
|
|
75
|
+
state.pinned[id] = s;
|
|
76
|
+
this.persist(project, state);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
unpin(id, project = 'default') {
|
|
82
|
+
const state = this.loadState(project);
|
|
83
|
+
delete state.pinned[id];
|
|
84
|
+
this.persist(project, state);
|
|
85
|
+
}
|
|
86
|
+
/** Called when the user has been idle — surface what matters now. */
|
|
87
|
+
async idleCheck(project, idleSinceMs) {
|
|
88
|
+
// Idle boosts priority by adding an idle marker event
|
|
89
|
+
this.observe({ type: 'idle', project, ts: Date.now(), payload: { idleSinceMs } });
|
|
90
|
+
return this.suggestions(project, { topN: 3 });
|
|
91
|
+
}
|
|
92
|
+
// ── Rules ───────────────────────────────────────────────────────────
|
|
93
|
+
registerRules() {
|
|
94
|
+
// Rule 1: Stale refactor reminder
|
|
95
|
+
this.rules.push({
|
|
96
|
+
id: 'stale-refactor',
|
|
97
|
+
detect: (events, _project, now) => {
|
|
98
|
+
const threeDays = 3 * 24 * 3600 * 1000;
|
|
99
|
+
const refactors = events.filter(e => e.type === 'file.refactor.start');
|
|
100
|
+
for (const r of refactors) {
|
|
101
|
+
if (now - r.ts < threeDays)
|
|
102
|
+
continue;
|
|
103
|
+
const file = String(r.payload?.file ?? 'unknown');
|
|
104
|
+
const committed = events.some(e => e.type === 'commit' && e.ts > r.ts &&
|
|
105
|
+
Array.isArray(e.payload?.files) &&
|
|
106
|
+
e.payload.files.includes(file));
|
|
107
|
+
if (committed)
|
|
108
|
+
continue;
|
|
109
|
+
return mkSuggestion({
|
|
110
|
+
id: `stale-refactor:${hashId(file + r.ts)}`,
|
|
111
|
+
kind: 'reminder',
|
|
112
|
+
priority: 0.75,
|
|
113
|
+
title: 'Stale refactor detected',
|
|
114
|
+
body: `You started refactoring \`${file}\` ${daysAgo(r.ts, now)} days ago but haven't committed. Want to review or pick it up?`,
|
|
115
|
+
evidence: [`file.refactor.start @ ${new Date(r.ts).toISOString()}`],
|
|
116
|
+
emoji: '🧹',
|
|
117
|
+
actionHints: [`git diff -- ${file}`, `shadow-brain replay ${file}`],
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
// Rule 2: Repeated debug pattern
|
|
124
|
+
this.rules.push({
|
|
125
|
+
id: 'debug-pattern',
|
|
126
|
+
detect: (events, _project, _now) => {
|
|
127
|
+
const debugs = events.filter(e => e.type === 'debug.attempt');
|
|
128
|
+
const counts = {};
|
|
129
|
+
for (const d of debugs) {
|
|
130
|
+
const tag = String(d.payload?.tag ?? d.payload?.category ?? 'general');
|
|
131
|
+
counts[tag] = (counts[tag] || 0) + 1;
|
|
132
|
+
}
|
|
133
|
+
const top = Object.entries(counts).sort((a, b) => b[1] - a[1])[0];
|
|
134
|
+
if (!top || top[1] < 5)
|
|
135
|
+
return null;
|
|
136
|
+
return mkSuggestion({
|
|
137
|
+
id: `debug-pattern:${top[0]}`,
|
|
138
|
+
kind: 'pattern-spotted',
|
|
139
|
+
priority: 0.65,
|
|
140
|
+
title: 'Recurring bug pattern',
|
|
141
|
+
body: `You've debugged ${top[0]} bugs ${top[1]} times. Consider extracting a helper or writing a regression suite.`,
|
|
142
|
+
evidence: [`${top[1]}x debug.attempt tag=${top[0]}`],
|
|
143
|
+
emoji: '🔁',
|
|
144
|
+
actionHints: [`shadow-brain dna ${top[0]}`, `Write a tiny test fixture`],
|
|
145
|
+
});
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
// Rule 3: Unconfirmed memories — triage nudge
|
|
149
|
+
this.rules.push({
|
|
150
|
+
id: 'unconfirmed-memories',
|
|
151
|
+
detect: (events, _project, _now) => {
|
|
152
|
+
const unconfirmed = events.filter(e => e.type === 'memory.unconfirmed').length;
|
|
153
|
+
if (unconfirmed < 5)
|
|
154
|
+
return null;
|
|
155
|
+
return mkSuggestion({
|
|
156
|
+
id: `unconfirmed-memories:${Math.floor(unconfirmed / 5) * 5}`,
|
|
157
|
+
kind: 'next-action',
|
|
158
|
+
priority: 0.55,
|
|
159
|
+
title: 'Memories waiting for triage',
|
|
160
|
+
body: `Your brain has ${unconfirmed} unconfirmed memories. Want to confirm or prune them?`,
|
|
161
|
+
evidence: [`${unconfirmed}x memory.unconfirmed`],
|
|
162
|
+
emoji: '📥',
|
|
163
|
+
actionHints: [`shadow-brain memory triage`, `shadow-brain memory list --unconfirmed`],
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
// Rule 4: Merge thrashing warning
|
|
168
|
+
this.rules.push({
|
|
169
|
+
id: 'merge-thrash',
|
|
170
|
+
detect: (events, _project, now) => {
|
|
171
|
+
const recent = events.filter(e => e.type === 'commit' && now - e.ts < 6 * 3600 * 1000).slice(-3);
|
|
172
|
+
if (recent.length < 3)
|
|
173
|
+
return null;
|
|
174
|
+
const lineCounts = {};
|
|
175
|
+
for (const c of recent) {
|
|
176
|
+
const file = String(c.payload?.file ?? '');
|
|
177
|
+
const line = Number(c.payload?.line ?? -1);
|
|
178
|
+
if (!file || line < 0)
|
|
179
|
+
continue;
|
|
180
|
+
const k = `${file}:${line}`;
|
|
181
|
+
lineCounts[k] = (lineCounts[k] || 0) + 1;
|
|
182
|
+
}
|
|
183
|
+
for (const [k, n] of Object.entries(lineCounts)) {
|
|
184
|
+
if (n < 3)
|
|
185
|
+
continue;
|
|
186
|
+
return mkSuggestion({
|
|
187
|
+
id: `merge-thrash:${hashId(k)}`,
|
|
188
|
+
kind: 'warning',
|
|
189
|
+
priority: 0.85,
|
|
190
|
+
title: 'Possible merge thrashing',
|
|
191
|
+
body: `Your last 3 commits modified \`${k}\` repeatedly. Possible flip-flop between branches or unresolved indecision.`,
|
|
192
|
+
evidence: [`3x commit at ${k}`],
|
|
193
|
+
emoji: '⚠️',
|
|
194
|
+
actionHints: [`git log -p -- ${k.split(':')[0]}`, `Pair-program the decision`],
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
},
|
|
199
|
+
});
|
|
200
|
+
// Rule 5: Memory milestone — celebrate
|
|
201
|
+
this.rules.push({
|
|
202
|
+
id: 'memory-milestone',
|
|
203
|
+
detect: (events, project, _now) => {
|
|
204
|
+
const adds = events.filter(e => e.type === 'memory.add').length;
|
|
205
|
+
const milestones = [10, 50, 100, 250, 500, 1000];
|
|
206
|
+
const hit = milestones.findLast ? milestones.findLast(m => adds >= m) : milestones.slice().reverse().find(m => adds >= m);
|
|
207
|
+
if (!hit)
|
|
208
|
+
return null;
|
|
209
|
+
return mkSuggestion({
|
|
210
|
+
id: `memory-milestone:${hit}`,
|
|
211
|
+
kind: 'celebrate',
|
|
212
|
+
priority: 0.5,
|
|
213
|
+
title: `${hit}th memory unlocked!`,
|
|
214
|
+
body: `Your ${project} brain just crossed ${hit} memories. Trophy time. ${hit >= 100 ? '🎉' : '🌱'}`,
|
|
215
|
+
evidence: [`${adds} total memory.add events`],
|
|
216
|
+
emoji: '🏆',
|
|
217
|
+
actionHints: [`shadow-brain trophies`, `shadow-brain dna --celebrate`],
|
|
218
|
+
});
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
// Rule 6: First capsule encouragement
|
|
222
|
+
this.rules.push({
|
|
223
|
+
id: 'first-capsule',
|
|
224
|
+
detect: (events, _project, _now) => {
|
|
225
|
+
const adds = events.filter(e => e.type === 'memory.add').length;
|
|
226
|
+
const freezes = events.filter(e => e.type === 'capsule.freeze').length;
|
|
227
|
+
if (adds < 20 || freezes > 0)
|
|
228
|
+
return null;
|
|
229
|
+
return mkSuggestion({
|
|
230
|
+
id: 'first-capsule:nudge',
|
|
231
|
+
kind: 'next-action',
|
|
232
|
+
priority: 0.45,
|
|
233
|
+
title: 'Freeze your first time capsule',
|
|
234
|
+
body: `You have ${adds} memories but no capsules. Freezing one preserves a snapshot for time-travel diffs.`,
|
|
235
|
+
evidence: [`${adds} memories, 0 capsules`],
|
|
236
|
+
emoji: '🧊',
|
|
237
|
+
actionHints: [`shadow-brain capsule freeze`, `shadow-brain replay --help`],
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
// Rule 7: Hive idle — invite collaboration
|
|
242
|
+
this.rules.push({
|
|
243
|
+
id: 'hive-idle',
|
|
244
|
+
detect: (events, _project, now) => {
|
|
245
|
+
const agents = events.filter(e => e.type === 'agent.spawn').length;
|
|
246
|
+
if (agents < 2)
|
|
247
|
+
return null;
|
|
248
|
+
const lastShare = events.filter(e => e.type === 'hive.share').pop();
|
|
249
|
+
const idle = !lastShare || now - lastShare.ts > 7 * 24 * 3600 * 1000;
|
|
250
|
+
if (!idle)
|
|
251
|
+
return null;
|
|
252
|
+
return mkSuggestion({
|
|
253
|
+
id: 'hive-idle:share',
|
|
254
|
+
kind: 'next-action',
|
|
255
|
+
priority: 0.4,
|
|
256
|
+
title: 'Your hive has gone quiet',
|
|
257
|
+
body: `You have ${agents} agents but no recent shares. Try \`shadow-brain hive sync\` to broadcast learnings.`,
|
|
258
|
+
evidence: [`${agents} agents, last share > 7d ago or never`],
|
|
259
|
+
emoji: '🐝',
|
|
260
|
+
actionHints: [`shadow-brain hive sync`, `shadow-brain hive status`],
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
// Rule 8: Constitution violation streak
|
|
265
|
+
this.rules.push({
|
|
266
|
+
id: 'constitution-streak',
|
|
267
|
+
detect: (events, _project, now) => {
|
|
268
|
+
const oneWeek = 7 * 24 * 3600 * 1000;
|
|
269
|
+
const recent = events.filter(e => e.type === 'constitution.violation' && now - e.ts < oneWeek);
|
|
270
|
+
if (recent.length < 3)
|
|
271
|
+
return null;
|
|
272
|
+
return mkSuggestion({
|
|
273
|
+
id: `constitution-streak:${recent.length}`,
|
|
274
|
+
kind: 'warning',
|
|
275
|
+
priority: 0.8,
|
|
276
|
+
title: 'Constitution drift',
|
|
277
|
+
body: `${recent.length} constitution violations in the last week. A rule may be out-of-date or a habit is forming.`,
|
|
278
|
+
evidence: recent.slice(-3).map(e => String(e.payload?.rule ?? 'unknown rule')),
|
|
279
|
+
emoji: '📜',
|
|
280
|
+
actionHints: [`shadow-brain constitution review`, `shadow-brain constitution audit`],
|
|
281
|
+
});
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
// Rule 9: Search-no-add (researching but not capturing)
|
|
285
|
+
this.rules.push({
|
|
286
|
+
id: 'search-no-add',
|
|
287
|
+
detect: (events, _project, now) => {
|
|
288
|
+
const day = 24 * 3600 * 1000;
|
|
289
|
+
const recent = events.filter(e => now - e.ts < day);
|
|
290
|
+
const searches = recent.filter(e => e.type === 'memory.search').length;
|
|
291
|
+
const adds = recent.filter(e => e.type === 'memory.add').length;
|
|
292
|
+
if (searches < 10 || adds >= 2)
|
|
293
|
+
return null;
|
|
294
|
+
return mkSuggestion({
|
|
295
|
+
id: `search-no-add:${Math.floor(searches / 10) * 10}`,
|
|
296
|
+
kind: 'pattern-spotted',
|
|
297
|
+
priority: 0.5,
|
|
298
|
+
title: 'Lots of looking, little capturing',
|
|
299
|
+
body: `${searches} searches today, only ${adds} new memories. Are you forgetting to write down what you learn?`,
|
|
300
|
+
evidence: [`${searches} memory.search`, `${adds} memory.add (today)`],
|
|
301
|
+
emoji: '🔍',
|
|
302
|
+
actionHints: [`shadow-brain memory add --quick`, `Enable auto-capture`],
|
|
303
|
+
});
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
// Rule 10: Welcome back — long absence
|
|
307
|
+
this.rules.push({
|
|
308
|
+
id: 'welcome-back',
|
|
309
|
+
detect: (events, _project, now) => {
|
|
310
|
+
if (events.length === 0)
|
|
311
|
+
return null;
|
|
312
|
+
const prevEvents = events.slice(0, -1);
|
|
313
|
+
if (prevEvents.length === 0)
|
|
314
|
+
return null;
|
|
315
|
+
const lastBefore = prevEvents[prevEvents.length - 1];
|
|
316
|
+
const gap = now - lastBefore.ts;
|
|
317
|
+
const oneWeek = 7 * 24 * 3600 * 1000;
|
|
318
|
+
if (gap < oneWeek)
|
|
319
|
+
return null;
|
|
320
|
+
return mkSuggestion({
|
|
321
|
+
id: `welcome-back:${Math.floor(now / oneWeek)}`,
|
|
322
|
+
kind: 'celebrate',
|
|
323
|
+
priority: 0.35,
|
|
324
|
+
title: 'Welcome back',
|
|
325
|
+
body: `Your brain has been quiet for ${Math.floor(gap / (24 * 3600 * 1000))} days. Want a recap of where you left off?`,
|
|
326
|
+
evidence: [`Last activity: ${new Date(lastBefore.ts).toISOString()}`],
|
|
327
|
+
emoji: '👋',
|
|
328
|
+
actionHints: [`shadow-brain recap`, `shadow-brain timeline --last 7d`],
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
// ── Persistence ─────────────────────────────────────────────────────
|
|
334
|
+
loadState(project) {
|
|
335
|
+
const cached = this.states.get(project);
|
|
336
|
+
if (cached)
|
|
337
|
+
return cached;
|
|
338
|
+
const file = pathFor(project);
|
|
339
|
+
let state = { events: [], dismissed: {}, pinned: {}, surfaced: {} };
|
|
340
|
+
try {
|
|
341
|
+
if (fs.existsSync(file)) {
|
|
342
|
+
const raw = JSON.parse(fs.readFileSync(file, 'utf-8'));
|
|
343
|
+
if (raw.state)
|
|
344
|
+
state = { ...state, ...raw.state };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
catch { /* fresh state */ }
|
|
348
|
+
this.states.set(project, state);
|
|
349
|
+
return state;
|
|
350
|
+
}
|
|
351
|
+
persist(project, state) {
|
|
352
|
+
try {
|
|
353
|
+
fs.mkdirSync(COACH_DIR, { recursive: true });
|
|
354
|
+
const file = pathFor(project);
|
|
355
|
+
const tmp = file + '.tmp';
|
|
356
|
+
const wrapped = { schemaVersion: 1, state };
|
|
357
|
+
fs.writeFileSync(tmp, JSON.stringify(wrapped, null, 2));
|
|
358
|
+
fs.renameSync(tmp, file);
|
|
359
|
+
}
|
|
360
|
+
catch { /* non-fatal */ }
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
function pathFor(project) {
|
|
364
|
+
const safe = project.replace(/[^a-zA-Z0-9._-]+/g, '_').slice(0, 80) || 'default';
|
|
365
|
+
return path.join(COACH_DIR, `${safe}.json`);
|
|
366
|
+
}
|
|
367
|
+
function mkSuggestion(partial) {
|
|
368
|
+
return { ...partial, createdAt: Date.now() };
|
|
369
|
+
}
|
|
370
|
+
function daysAgo(ts, now) {
|
|
371
|
+
return Math.floor((now - ts) / (24 * 3600 * 1000));
|
|
372
|
+
}
|
|
373
|
+
function hashId(s) {
|
|
374
|
+
return crypto.createHash('sha1').update(s).digest('hex').slice(0, 10);
|
|
375
|
+
}
|
|
376
|
+
let _instance = null;
|
|
377
|
+
export function getBrainCoach() {
|
|
378
|
+
if (!_instance)
|
|
379
|
+
_instance = new BrainCoach();
|
|
380
|
+
return _instance;
|
|
381
|
+
}
|
|
382
|
+
export function resetBrainCoachForTests() { _instance = null; }
|
|
383
|
+
//# sourceMappingURL=brain-coach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-coach.js","sourceRoot":"","sources":["../../src/brain/brain-coach.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export interface RunOptions {
|
|
2
|
+
project?: string;
|
|
3
|
+
dryRun?: boolean;
|
|
4
|
+
/** Min cluster size for abstraction emission. Default 5. */
|
|
5
|
+
minCluster?: number;
|
|
6
|
+
/** Cosine similarity threshold for merge. Default 0.92. */
|
|
7
|
+
similarityThreshold?: number;
|
|
8
|
+
/** If true, archive episodic memories with accessCount=0 + age > 180d. */
|
|
9
|
+
prune?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface MergePair {
|
|
12
|
+
kept: string;
|
|
13
|
+
merged: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface Abstraction {
|
|
16
|
+
id: string;
|
|
17
|
+
abstractsOver: string[];
|
|
18
|
+
content: string;
|
|
19
|
+
}
|
|
20
|
+
export interface ConsolidationReport {
|
|
21
|
+
project: string;
|
|
22
|
+
startedAt: string;
|
|
23
|
+
durationMs: number;
|
|
24
|
+
scanned: number;
|
|
25
|
+
mergedPairs: MergePair[];
|
|
26
|
+
abstractionsCreated: Abstraction[];
|
|
27
|
+
pruned: string[];
|
|
28
|
+
dryRun: boolean;
|
|
29
|
+
similarityBackend: 'embeddings' | 'jaccard';
|
|
30
|
+
}
|
|
31
|
+
interface ScheduleHandle {
|
|
32
|
+
stop: () => void;
|
|
33
|
+
}
|
|
34
|
+
export declare class BrainConsolidator {
|
|
35
|
+
private lastReports;
|
|
36
|
+
private timers;
|
|
37
|
+
private initialized;
|
|
38
|
+
init(): Promise<void>;
|
|
39
|
+
run(opts?: RunOptions): Promise<ConsolidationReport>;
|
|
40
|
+
schedule(project: string, intervalMs: number): ScheduleHandle;
|
|
41
|
+
lastReport(project: string): ConsolidationReport | null;
|
|
42
|
+
previewMerge(memoryIds: string[]): Promise<{
|
|
43
|
+
wouldMerge: boolean;
|
|
44
|
+
mergedContent: string;
|
|
45
|
+
droppedFields: string[];
|
|
46
|
+
}>;
|
|
47
|
+
private similarityFn;
|
|
48
|
+
private writeMerge;
|
|
49
|
+
private makeAbstraction;
|
|
50
|
+
private archiveMemory;
|
|
51
|
+
private persistReport;
|
|
52
|
+
}
|
|
53
|
+
export declare function getBrainConsolidator(): BrainConsolidator;
|
|
54
|
+
export declare function resetBrainConsolidatorForTests(): void;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=brain-consolidator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brain-consolidator.d.ts","sourceRoot":"","sources":["../../src/brain/brain-consolidator.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,UAAU;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,0EAA0E;IAC1E,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,mBAAmB,EAAE,WAAW,EAAE,CAAC;IACnC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,iBAAiB,EAAE,YAAY,GAAG,SAAS,CAAC;CAC7C;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,WAAW,CAA0C;IAC7D,OAAO,CAAC,MAAM,CAAqC;IACnD,OAAO,CAAC,WAAW,CAAS;IAEtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrB,GAAG,CAAC,IAAI,GAAE,UAAe,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAyG9D,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,cAAc;IAiB7D,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAIjD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;YAsB3G,YAAY;YAoCZ,UAAU;YAyBV,eAAe;YAsBf,aAAa;YASb,aAAa;CAS5B;AA6DD,wBAAgB,oBAAoB,IAAI,iBAAiB,CAGxD;AACD,wBAAgB,8BAA8B,IAAI,IAAI,CAOrD"}
|