instar 0.6.13 → 0.6.14
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 +29 -0
- package/dist/cli.js +0 -0
- package/dist/commands/init.js +0 -9
- package/dist/commands/server.js +4 -37
- package/dist/core/RelationshipManager.d.ts +0 -67
- package/dist/core/RelationshipManager.js +4 -358
- package/dist/core/SessionManager.d.ts +1 -3
- package/dist/core/SessionManager.js +6 -14
- package/dist/core/types.d.ts +0 -212
- package/dist/index.d.ts +1 -4
- package/dist/index.js +0 -3
- package/dist/server/AgentServer.d.ts +0 -2
- package/dist/server/AgentServer.js +0 -1
- package/dist/server/routes.d.ts +0 -2
- package/dist/server/routes.js +0 -218
- package/package.json +1 -1
- package/.vercel/README.txt +0 -11
- package/.vercel/project.json +0 -1
- package/dist/core/AnthropicIntelligenceProvider.d.ts +0 -24
- package/dist/core/AnthropicIntelligenceProvider.js +0 -68
- package/dist/core/ClaudeCliIntelligenceProvider.d.ts +0 -21
- package/dist/core/ClaudeCliIntelligenceProvider.js +0 -59
- package/dist/core/EvolutionManager.d.ts +0 -157
- package/dist/core/EvolutionManager.js +0 -432
|
@@ -1,432 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Evolution Manager — the feedback loop that turns running into evolving.
|
|
3
|
-
*
|
|
4
|
-
* Four subsystems, one principle: every interaction is an opportunity
|
|
5
|
-
* to improve. Not during batch reflection hours later, but at the
|
|
6
|
-
* moment the insight is freshest.
|
|
7
|
-
*
|
|
8
|
-
* Subsystems:
|
|
9
|
-
* 1. Evolution Queue — staged self-improvement proposals
|
|
10
|
-
* 2. Learning Registry — structured, searchable insights
|
|
11
|
-
* 3. Capability Gap Tracker — "what am I missing?"
|
|
12
|
-
* 4. Action Queue — commitment tracking with stale detection
|
|
13
|
-
*
|
|
14
|
-
* Born from Portal's engagement pipeline (Steps 8-11) and proven
|
|
15
|
-
* across 100+ evolution proposals and 10 platform engagement skills.
|
|
16
|
-
*/
|
|
17
|
-
import fs from 'node:fs';
|
|
18
|
-
import path from 'node:path';
|
|
19
|
-
export class EvolutionManager {
|
|
20
|
-
stateDir;
|
|
21
|
-
config;
|
|
22
|
-
constructor(config) {
|
|
23
|
-
this.config = config;
|
|
24
|
-
this.stateDir = config.stateDir;
|
|
25
|
-
}
|
|
26
|
-
// ── File I/O ────────────────────────────────────────────────────
|
|
27
|
-
filePath(name) {
|
|
28
|
-
return path.join(this.stateDir, 'state', 'evolution', `${name}.json`);
|
|
29
|
-
}
|
|
30
|
-
readFile(name, defaultValue) {
|
|
31
|
-
const fp = this.filePath(name);
|
|
32
|
-
if (!fs.existsSync(fp))
|
|
33
|
-
return defaultValue;
|
|
34
|
-
try {
|
|
35
|
-
return JSON.parse(fs.readFileSync(fp, 'utf-8'));
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
console.warn(`[EvolutionManager] Corrupted file: ${fp}`);
|
|
39
|
-
return defaultValue;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
writeFile(name, data) {
|
|
43
|
-
const fp = this.filePath(name);
|
|
44
|
-
const dir = path.dirname(fp);
|
|
45
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
46
|
-
const tmpPath = fp + `.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
47
|
-
try {
|
|
48
|
-
fs.writeFileSync(tmpPath, JSON.stringify(data, null, 2));
|
|
49
|
-
fs.renameSync(tmpPath, fp);
|
|
50
|
-
}
|
|
51
|
-
catch (err) {
|
|
52
|
-
try {
|
|
53
|
-
fs.unlinkSync(tmpPath);
|
|
54
|
-
}
|
|
55
|
-
catch { /* ignore */ }
|
|
56
|
-
throw err;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
now() {
|
|
60
|
-
return new Date().toISOString();
|
|
61
|
-
}
|
|
62
|
-
// ── Evolution Queue ─────────────────────────────────────────────
|
|
63
|
-
loadEvolution() {
|
|
64
|
-
return this.readFile('evolution-queue', {
|
|
65
|
-
proposals: [],
|
|
66
|
-
stats: { totalProposals: 0, byStatus: {}, byType: {}, lastUpdated: this.now() },
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
saveEvolution(state) {
|
|
70
|
-
// Recompute stats
|
|
71
|
-
const statusCounts = {};
|
|
72
|
-
const typeCounts = {};
|
|
73
|
-
for (const p of state.proposals) {
|
|
74
|
-
statusCounts[p.status] = (statusCounts[p.status] || 0) + 1;
|
|
75
|
-
typeCounts[p.type] = (typeCounts[p.type] || 0) + 1;
|
|
76
|
-
}
|
|
77
|
-
state.stats = {
|
|
78
|
-
totalProposals: state.proposals.length,
|
|
79
|
-
byStatus: statusCounts,
|
|
80
|
-
byType: typeCounts,
|
|
81
|
-
lastUpdated: this.now(),
|
|
82
|
-
};
|
|
83
|
-
// Archive old implemented/rejected proposals if over limit
|
|
84
|
-
const max = this.config.maxProposals || 200;
|
|
85
|
-
if (state.proposals.length > max) {
|
|
86
|
-
const active = state.proposals.filter(p => !['implemented', 'rejected'].includes(p.status));
|
|
87
|
-
const archived = state.proposals.filter(p => ['implemented', 'rejected'].includes(p.status));
|
|
88
|
-
// Keep most recent archived
|
|
89
|
-
const keep = archived.slice(-Math.max(0, max - active.length));
|
|
90
|
-
state.proposals = [...active, ...keep];
|
|
91
|
-
}
|
|
92
|
-
this.writeFile('evolution-queue', state);
|
|
93
|
-
}
|
|
94
|
-
nextProposalId(state) {
|
|
95
|
-
const existing = new Set(state.proposals.map(p => p.id));
|
|
96
|
-
let num = 1;
|
|
97
|
-
while (existing.has(`EVO-${String(num).padStart(3, '0')}`))
|
|
98
|
-
num++;
|
|
99
|
-
return `EVO-${String(num).padStart(3, '0')}`;
|
|
100
|
-
}
|
|
101
|
-
addProposal(opts) {
|
|
102
|
-
const state = this.loadEvolution();
|
|
103
|
-
const id = this.nextProposalId(state);
|
|
104
|
-
const proposal = {
|
|
105
|
-
id,
|
|
106
|
-
title: opts.title,
|
|
107
|
-
source: opts.source,
|
|
108
|
-
description: opts.description,
|
|
109
|
-
type: opts.type,
|
|
110
|
-
impact: opts.impact || 'medium',
|
|
111
|
-
effort: opts.effort || 'medium',
|
|
112
|
-
status: 'proposed',
|
|
113
|
-
proposedBy: opts.proposedBy || 'agent',
|
|
114
|
-
proposedAt: this.now(),
|
|
115
|
-
tags: opts.tags,
|
|
116
|
-
};
|
|
117
|
-
state.proposals.push(proposal);
|
|
118
|
-
this.saveEvolution(state);
|
|
119
|
-
return proposal;
|
|
120
|
-
}
|
|
121
|
-
updateProposalStatus(id, status, resolution) {
|
|
122
|
-
const state = this.loadEvolution();
|
|
123
|
-
const proposal = state.proposals.find(p => p.id === id);
|
|
124
|
-
if (!proposal)
|
|
125
|
-
return false;
|
|
126
|
-
proposal.status = status;
|
|
127
|
-
if (resolution)
|
|
128
|
-
proposal.resolution = resolution;
|
|
129
|
-
if (status === 'implemented')
|
|
130
|
-
proposal.implementedAt = this.now();
|
|
131
|
-
this.saveEvolution(state);
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
listProposals(filter) {
|
|
135
|
-
const state = this.loadEvolution();
|
|
136
|
-
let proposals = state.proposals;
|
|
137
|
-
if (filter?.status)
|
|
138
|
-
proposals = proposals.filter(p => p.status === filter.status);
|
|
139
|
-
if (filter?.type)
|
|
140
|
-
proposals = proposals.filter(p => p.type === filter.type);
|
|
141
|
-
return proposals;
|
|
142
|
-
}
|
|
143
|
-
getEvolutionStats() {
|
|
144
|
-
return this.loadEvolution().stats;
|
|
145
|
-
}
|
|
146
|
-
// ── Learning Registry ───────────────────────────────────────────
|
|
147
|
-
loadLearnings() {
|
|
148
|
-
return this.readFile('learning-registry', {
|
|
149
|
-
learnings: [],
|
|
150
|
-
stats: { totalLearnings: 0, applied: 0, pending: 0, byCategory: {}, lastUpdated: this.now() },
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
saveLearnings(state) {
|
|
154
|
-
const categoryCounts = {};
|
|
155
|
-
let applied = 0;
|
|
156
|
-
for (const l of state.learnings) {
|
|
157
|
-
categoryCounts[l.category] = (categoryCounts[l.category] || 0) + 1;
|
|
158
|
-
if (l.applied)
|
|
159
|
-
applied++;
|
|
160
|
-
}
|
|
161
|
-
state.stats = {
|
|
162
|
-
totalLearnings: state.learnings.length,
|
|
163
|
-
applied,
|
|
164
|
-
pending: state.learnings.length - applied,
|
|
165
|
-
byCategory: categoryCounts,
|
|
166
|
-
lastUpdated: this.now(),
|
|
167
|
-
};
|
|
168
|
-
const max = this.config.maxLearnings || 500;
|
|
169
|
-
if (state.learnings.length > max) {
|
|
170
|
-
const unapplied = state.learnings.filter(l => !l.applied);
|
|
171
|
-
const appliedEntries = state.learnings.filter(l => l.applied);
|
|
172
|
-
const keep = appliedEntries.slice(-Math.max(0, max - unapplied.length));
|
|
173
|
-
state.learnings = [...unapplied, ...keep];
|
|
174
|
-
}
|
|
175
|
-
this.writeFile('learning-registry', state);
|
|
176
|
-
}
|
|
177
|
-
nextLearningId(state) {
|
|
178
|
-
const existing = new Set(state.learnings.map(l => l.id));
|
|
179
|
-
let num = 1;
|
|
180
|
-
while (existing.has(`LRN-${String(num).padStart(3, '0')}`))
|
|
181
|
-
num++;
|
|
182
|
-
return `LRN-${String(num).padStart(3, '0')}`;
|
|
183
|
-
}
|
|
184
|
-
addLearning(opts) {
|
|
185
|
-
const state = this.loadLearnings();
|
|
186
|
-
const id = this.nextLearningId(state);
|
|
187
|
-
const learning = {
|
|
188
|
-
id,
|
|
189
|
-
title: opts.title,
|
|
190
|
-
category: opts.category,
|
|
191
|
-
description: opts.description,
|
|
192
|
-
source: opts.source,
|
|
193
|
-
tags: opts.tags || [],
|
|
194
|
-
applied: false,
|
|
195
|
-
evolutionRelevance: opts.evolutionRelevance,
|
|
196
|
-
};
|
|
197
|
-
state.learnings.push(learning);
|
|
198
|
-
this.saveLearnings(state);
|
|
199
|
-
return learning;
|
|
200
|
-
}
|
|
201
|
-
markLearningApplied(id, appliedTo) {
|
|
202
|
-
const state = this.loadLearnings();
|
|
203
|
-
const learning = state.learnings.find(l => l.id === id);
|
|
204
|
-
if (!learning)
|
|
205
|
-
return false;
|
|
206
|
-
learning.applied = true;
|
|
207
|
-
learning.appliedTo = appliedTo;
|
|
208
|
-
this.saveLearnings(state);
|
|
209
|
-
return true;
|
|
210
|
-
}
|
|
211
|
-
listLearnings(filter) {
|
|
212
|
-
const state = this.loadLearnings();
|
|
213
|
-
let learnings = state.learnings;
|
|
214
|
-
if (filter?.category)
|
|
215
|
-
learnings = learnings.filter(l => l.category === filter.category);
|
|
216
|
-
if (filter?.applied !== undefined)
|
|
217
|
-
learnings = learnings.filter(l => l.applied === filter.applied);
|
|
218
|
-
return learnings;
|
|
219
|
-
}
|
|
220
|
-
getLearningStats() {
|
|
221
|
-
return this.loadLearnings().stats;
|
|
222
|
-
}
|
|
223
|
-
// ── Capability Gap Tracker ──────────────────────────────────────
|
|
224
|
-
loadGaps() {
|
|
225
|
-
return this.readFile('capability-gaps', {
|
|
226
|
-
gaps: [],
|
|
227
|
-
stats: { totalGaps: 0, bySeverity: {}, byCategory: {}, addressed: 0, lastUpdated: this.now() },
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
saveGaps(state) {
|
|
231
|
-
const severityCounts = {};
|
|
232
|
-
const categoryCounts = {};
|
|
233
|
-
let addressed = 0;
|
|
234
|
-
for (const g of state.gaps) {
|
|
235
|
-
severityCounts[g.severity] = (severityCounts[g.severity] || 0) + 1;
|
|
236
|
-
categoryCounts[g.category] = (categoryCounts[g.category] || 0) + 1;
|
|
237
|
-
if (g.status === 'addressed')
|
|
238
|
-
addressed++;
|
|
239
|
-
}
|
|
240
|
-
state.stats = {
|
|
241
|
-
totalGaps: state.gaps.length,
|
|
242
|
-
bySeverity: severityCounts,
|
|
243
|
-
byCategory: categoryCounts,
|
|
244
|
-
addressed,
|
|
245
|
-
lastUpdated: this.now(),
|
|
246
|
-
};
|
|
247
|
-
const max = this.config.maxGaps || 200;
|
|
248
|
-
if (state.gaps.length > max) {
|
|
249
|
-
const open = state.gaps.filter(g => g.status === 'identified');
|
|
250
|
-
const closed = state.gaps.filter(g => g.status !== 'identified');
|
|
251
|
-
const keep = closed.slice(-Math.max(0, max - open.length));
|
|
252
|
-
state.gaps = [...open, ...keep];
|
|
253
|
-
}
|
|
254
|
-
this.writeFile('capability-gaps', state);
|
|
255
|
-
}
|
|
256
|
-
nextGapId(state) {
|
|
257
|
-
const existing = new Set(state.gaps.map(g => g.id));
|
|
258
|
-
let num = 1;
|
|
259
|
-
while (existing.has(`GAP-${String(num).padStart(3, '0')}`))
|
|
260
|
-
num++;
|
|
261
|
-
return `GAP-${String(num).padStart(3, '0')}`;
|
|
262
|
-
}
|
|
263
|
-
addGap(opts) {
|
|
264
|
-
const state = this.loadGaps();
|
|
265
|
-
const id = this.nextGapId(state);
|
|
266
|
-
const gap = {
|
|
267
|
-
id,
|
|
268
|
-
title: opts.title,
|
|
269
|
-
category: opts.category,
|
|
270
|
-
severity: opts.severity,
|
|
271
|
-
description: opts.description,
|
|
272
|
-
discoveredFrom: {
|
|
273
|
-
context: opts.context,
|
|
274
|
-
platform: opts.platform,
|
|
275
|
-
discoveredAt: this.now(),
|
|
276
|
-
session: opts.session,
|
|
277
|
-
},
|
|
278
|
-
currentState: opts.currentState || 'Not implemented',
|
|
279
|
-
proposedSolution: opts.proposedSolution,
|
|
280
|
-
status: 'identified',
|
|
281
|
-
};
|
|
282
|
-
state.gaps.push(gap);
|
|
283
|
-
this.saveGaps(state);
|
|
284
|
-
return gap;
|
|
285
|
-
}
|
|
286
|
-
addressGap(id, resolution) {
|
|
287
|
-
const state = this.loadGaps();
|
|
288
|
-
const gap = state.gaps.find(g => g.id === id);
|
|
289
|
-
if (!gap)
|
|
290
|
-
return false;
|
|
291
|
-
gap.status = 'addressed';
|
|
292
|
-
gap.resolution = resolution;
|
|
293
|
-
gap.addressedAt = this.now();
|
|
294
|
-
this.saveGaps(state);
|
|
295
|
-
return true;
|
|
296
|
-
}
|
|
297
|
-
listGaps(filter) {
|
|
298
|
-
const state = this.loadGaps();
|
|
299
|
-
let gaps = state.gaps;
|
|
300
|
-
if (filter?.severity)
|
|
301
|
-
gaps = gaps.filter(g => g.severity === filter.severity);
|
|
302
|
-
if (filter?.category)
|
|
303
|
-
gaps = gaps.filter(g => g.category === filter.category);
|
|
304
|
-
if (filter?.status)
|
|
305
|
-
gaps = gaps.filter(g => g.status === filter.status);
|
|
306
|
-
return gaps;
|
|
307
|
-
}
|
|
308
|
-
getGapStats() {
|
|
309
|
-
return this.loadGaps().stats;
|
|
310
|
-
}
|
|
311
|
-
// ── Action Queue ────────────────────────────────────────────────
|
|
312
|
-
loadActions() {
|
|
313
|
-
return this.readFile('action-queue', {
|
|
314
|
-
actions: [],
|
|
315
|
-
stats: { totalActions: 0, pending: 0, completed: 0, overdue: 0, lastUpdated: this.now() },
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
saveActions(state) {
|
|
319
|
-
let pending = 0, completed = 0, overdue = 0;
|
|
320
|
-
const now = new Date();
|
|
321
|
-
for (const a of state.actions) {
|
|
322
|
-
if (a.status === 'completed')
|
|
323
|
-
completed++;
|
|
324
|
-
else if (a.status === 'pending' || a.status === 'in_progress') {
|
|
325
|
-
pending++;
|
|
326
|
-
if (a.dueBy && new Date(a.dueBy) < now)
|
|
327
|
-
overdue++;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
state.stats = {
|
|
331
|
-
totalActions: state.actions.length,
|
|
332
|
-
pending,
|
|
333
|
-
completed,
|
|
334
|
-
overdue,
|
|
335
|
-
lastUpdated: this.now(),
|
|
336
|
-
};
|
|
337
|
-
const max = this.config.maxActions || 300;
|
|
338
|
-
if (state.actions.length > max) {
|
|
339
|
-
const active = state.actions.filter(a => !['completed', 'cancelled'].includes(a.status));
|
|
340
|
-
const done = state.actions.filter(a => ['completed', 'cancelled'].includes(a.status));
|
|
341
|
-
const keep = done.slice(-Math.max(0, max - active.length));
|
|
342
|
-
state.actions = [...active, ...keep];
|
|
343
|
-
}
|
|
344
|
-
this.writeFile('action-queue', state);
|
|
345
|
-
}
|
|
346
|
-
nextActionId(state) {
|
|
347
|
-
const existing = new Set(state.actions.map(a => a.id));
|
|
348
|
-
let num = 1;
|
|
349
|
-
while (existing.has(`ACT-${String(num).padStart(3, '0')}`))
|
|
350
|
-
num++;
|
|
351
|
-
return `ACT-${String(num).padStart(3, '0')}`;
|
|
352
|
-
}
|
|
353
|
-
addAction(opts) {
|
|
354
|
-
const state = this.loadActions();
|
|
355
|
-
const id = this.nextActionId(state);
|
|
356
|
-
const action = {
|
|
357
|
-
id,
|
|
358
|
-
title: opts.title,
|
|
359
|
-
description: opts.description,
|
|
360
|
-
priority: opts.priority || 'medium',
|
|
361
|
-
status: 'pending',
|
|
362
|
-
commitTo: opts.commitTo,
|
|
363
|
-
createdAt: this.now(),
|
|
364
|
-
dueBy: opts.dueBy,
|
|
365
|
-
source: opts.source,
|
|
366
|
-
tags: opts.tags,
|
|
367
|
-
};
|
|
368
|
-
state.actions.push(action);
|
|
369
|
-
this.saveActions(state);
|
|
370
|
-
return action;
|
|
371
|
-
}
|
|
372
|
-
updateAction(id, updates) {
|
|
373
|
-
const state = this.loadActions();
|
|
374
|
-
const action = state.actions.find(a => a.id === id);
|
|
375
|
-
if (!action)
|
|
376
|
-
return false;
|
|
377
|
-
if (updates.status) {
|
|
378
|
-
action.status = updates.status;
|
|
379
|
-
if (updates.status === 'completed')
|
|
380
|
-
action.completedAt = this.now();
|
|
381
|
-
}
|
|
382
|
-
if (updates.resolution)
|
|
383
|
-
action.resolution = updates.resolution;
|
|
384
|
-
this.saveActions(state);
|
|
385
|
-
return true;
|
|
386
|
-
}
|
|
387
|
-
listActions(filter) {
|
|
388
|
-
const state = this.loadActions();
|
|
389
|
-
let actions = state.actions;
|
|
390
|
-
if (filter?.status)
|
|
391
|
-
actions = actions.filter(a => a.status === filter.status);
|
|
392
|
-
if (filter?.priority)
|
|
393
|
-
actions = actions.filter(a => a.priority === filter.priority);
|
|
394
|
-
return actions;
|
|
395
|
-
}
|
|
396
|
-
getOverdueActions() {
|
|
397
|
-
const state = this.loadActions();
|
|
398
|
-
const now = new Date();
|
|
399
|
-
return state.actions.filter(a => (a.status === 'pending' || a.status === 'in_progress') &&
|
|
400
|
-
a.dueBy && new Date(a.dueBy) < now);
|
|
401
|
-
}
|
|
402
|
-
getActionStats() {
|
|
403
|
-
return this.loadActions().stats;
|
|
404
|
-
}
|
|
405
|
-
// ── Cross-System Queries ────────────────────────────────────────
|
|
406
|
-
/**
|
|
407
|
-
* Get a full dashboard of evolution health.
|
|
408
|
-
* Useful for session-start orientation and status reporting.
|
|
409
|
-
*/
|
|
410
|
-
getDashboard() {
|
|
411
|
-
const evolution = this.getEvolutionStats();
|
|
412
|
-
const learnings = this.getLearningStats();
|
|
413
|
-
const gaps = this.getGapStats();
|
|
414
|
-
const actions = this.getActionStats();
|
|
415
|
-
const overdue = this.getOverdueActions();
|
|
416
|
-
const highlights = [];
|
|
417
|
-
const proposed = evolution.byStatus['proposed'] || 0;
|
|
418
|
-
if (proposed > 0)
|
|
419
|
-
highlights.push(`${proposed} evolution proposal(s) awaiting review`);
|
|
420
|
-
if (learnings.pending > 0)
|
|
421
|
-
highlights.push(`${learnings.pending} learning(s) not yet applied`);
|
|
422
|
-
const criticalGaps = gaps.bySeverity['critical'] || 0;
|
|
423
|
-
if (criticalGaps > 0)
|
|
424
|
-
highlights.push(`${criticalGaps} critical capability gap(s)`);
|
|
425
|
-
if (overdue.length > 0)
|
|
426
|
-
highlights.push(`${overdue.length} overdue action item(s)`);
|
|
427
|
-
if (highlights.length === 0)
|
|
428
|
-
highlights.push('All systems healthy — no pending evolution items');
|
|
429
|
-
return { evolution, learnings, gaps, actions, highlights };
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
//# sourceMappingURL=EvolutionManager.js.map
|