@cleocode/cleo 2026.4.37 → 2026.4.39
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/dist/cli/commands/brain.d.ts.map +1 -1
- package/dist/cli/commands/brain.js +60 -1
- package/dist/cli/commands/brain.js.map +1 -1
- package/dist/cli/commands/memory-brain.d.ts.map +1 -1
- package/dist/cli/commands/memory-brain.js +38 -0
- package/dist/cli/commands/memory-brain.js.map +1 -1
- package/dist/cli/commands/nexus.d.ts.map +1 -1
- package/dist/cli/commands/nexus.js +75 -2
- package/dist/cli/commands/nexus.js.map +1 -1
- package/dist/cli/index.js +1309 -40
- package/dist/cli/index.js.map +4 -4
- package/dist/dispatch/domains/memory.d.ts.map +1 -1
- package/dist/dispatch/domains/memory.js +6 -1
- package/dist/dispatch/domains/memory.js.map +1 -1
- package/dist/dispatch/engines/memory-engine.d.ts +1 -1
- package/dist/dispatch/engines/memory-engine.d.ts.map +1 -1
- package/dist/dispatch/engines/memory-engine.js +1 -1
- package/dist/dispatch/engines/memory-engine.js.map +1 -1
- package/dist/dispatch/engines/orchestrate-engine.d.ts.map +1 -1
- package/dist/dispatch/engines/orchestrate-engine.js +50 -0
- package/dist/dispatch/engines/orchestrate-engine.js.map +1 -1
- package/dist/dispatch/lib/engine.d.ts +1 -1
- package/dist/dispatch/lib/engine.d.ts.map +1 -1
- package/dist/dispatch/lib/engine.js +1 -1
- package/dist/dispatch/lib/engine.js.map +1 -1
- package/dist/dispatch/registry.d.ts.map +1 -1
- package/dist/dispatch/registry.js +89 -0
- package/dist/dispatch/registry.js.map +1 -1
- package/dist/dispatch/types.d.ts +1 -1
- package/dist/dispatch/types.d.ts.map +1 -1
- package/dist/dispatch/types.js +1 -0
- package/dist/dispatch/types.js.map +1 -1
- package/package.json +8 -8
package/dist/cli/index.js
CHANGED
|
@@ -22109,6 +22109,210 @@ var init_quality_scoring = __esm({
|
|
|
22109
22109
|
}
|
|
22110
22110
|
});
|
|
22111
22111
|
|
|
22112
|
+
// packages/core/src/store/typed-query.ts
|
|
22113
|
+
function typedAll(stmt, ...params) {
|
|
22114
|
+
return stmt.all(...params);
|
|
22115
|
+
}
|
|
22116
|
+
function typedGet(stmt, ...params) {
|
|
22117
|
+
return stmt.get(...params);
|
|
22118
|
+
}
|
|
22119
|
+
var init_typed_query = __esm({
|
|
22120
|
+
"packages/core/src/store/typed-query.ts"() {
|
|
22121
|
+
"use strict";
|
|
22122
|
+
}
|
|
22123
|
+
});
|
|
22124
|
+
|
|
22125
|
+
// packages/core/src/memory/temporal-supersession.ts
|
|
22126
|
+
function extractKeywords(text3) {
|
|
22127
|
+
const words = text3.toLowerCase().replace(/[^a-z0-9\s\-_]/g, " ").split(/\s+/);
|
|
22128
|
+
const keywords = /* @__PURE__ */ new Set();
|
|
22129
|
+
for (const w2 of words) {
|
|
22130
|
+
if (w2.length >= 4 && !STOP_WORDS.has(w2)) {
|
|
22131
|
+
keywords.add(w2);
|
|
22132
|
+
}
|
|
22133
|
+
}
|
|
22134
|
+
return keywords;
|
|
22135
|
+
}
|
|
22136
|
+
function keywordSimilarity(textA, textB) {
|
|
22137
|
+
const kwA = extractKeywords(textA);
|
|
22138
|
+
const kwB = extractKeywords(textB);
|
|
22139
|
+
if (kwA.size === 0 || kwB.size === 0) return { similarity: 0, shared: [] };
|
|
22140
|
+
const shared = [];
|
|
22141
|
+
for (const w2 of kwA) {
|
|
22142
|
+
if (kwB.has(w2)) shared.push(w2);
|
|
22143
|
+
}
|
|
22144
|
+
if (shared.length < MIN_SHARED_KEYWORDS) return { similarity: 0, shared: [] };
|
|
22145
|
+
const union3 = kwA.size + kwB.size - shared.length;
|
|
22146
|
+
const similarity = union3 > 0 ? shared.length / union3 : 0;
|
|
22147
|
+
return { similarity, shared };
|
|
22148
|
+
}
|
|
22149
|
+
function buildNodeId(type, entryId) {
|
|
22150
|
+
return `${type}:${entryId}`;
|
|
22151
|
+
}
|
|
22152
|
+
async function locateEntry(projectRoot, entryId) {
|
|
22153
|
+
await getBrainDb(projectRoot);
|
|
22154
|
+
const nativeDb = getBrainNativeDb();
|
|
22155
|
+
if (!nativeDb) return null;
|
|
22156
|
+
for (const tc of SUPERSEDABLE_TABLES) {
|
|
22157
|
+
const row = typedGet(
|
|
22158
|
+
nativeDb.prepare(`SELECT id FROM ${tc.table} WHERE id = ? LIMIT 1`),
|
|
22159
|
+
entryId
|
|
22160
|
+
);
|
|
22161
|
+
if (row) {
|
|
22162
|
+
return { tableConfig: tc, nodeId: buildNodeId(tc.type, entryId) };
|
|
22163
|
+
}
|
|
22164
|
+
}
|
|
22165
|
+
return null;
|
|
22166
|
+
}
|
|
22167
|
+
async function supersedeMemory(projectRoot, oldId, newId, reason) {
|
|
22168
|
+
if (!oldId?.trim()) throw new Error("oldId is required");
|
|
22169
|
+
if (!newId?.trim()) throw new Error("newId is required");
|
|
22170
|
+
if (!reason?.trim()) throw new Error("reason is required");
|
|
22171
|
+
if (oldId === newId) throw new Error("oldId and newId must be different entries");
|
|
22172
|
+
await getBrainDb(projectRoot);
|
|
22173
|
+
const nativeDb = getBrainNativeDb();
|
|
22174
|
+
if (!nativeDb) throw new Error("brain.db is unavailable");
|
|
22175
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
22176
|
+
const oldLocation = await locateEntry(projectRoot, oldId);
|
|
22177
|
+
if (!oldLocation) throw new Error(`Entry not found: ${oldId}`);
|
|
22178
|
+
const newLocation = await locateEntry(projectRoot, newId);
|
|
22179
|
+
if (!newLocation) throw new Error(`Entry not found: ${newId}`);
|
|
22180
|
+
const { tableConfig: oldTc, nodeId: oldNodeId } = oldLocation;
|
|
22181
|
+
const { nodeId: newNodeId } = newLocation;
|
|
22182
|
+
try {
|
|
22183
|
+
nativeDb.prepare(
|
|
22184
|
+
`UPDATE ${oldTc.table} SET invalid_at = ?, updated_at = ? WHERE id = ? AND invalid_at IS NULL`
|
|
22185
|
+
).run(now2, now2, oldId);
|
|
22186
|
+
} catch {
|
|
22187
|
+
}
|
|
22188
|
+
const provenanceText = reason.substring(0, 500);
|
|
22189
|
+
try {
|
|
22190
|
+
nativeDb.prepare(
|
|
22191
|
+
`INSERT OR IGNORE INTO brain_page_edges
|
|
22192
|
+
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
22193
|
+
VALUES (?, ?, 'supersedes', 1.0, ?, ?)`
|
|
22194
|
+
).run(newNodeId, oldNodeId, provenanceText, now2);
|
|
22195
|
+
} catch (err) {
|
|
22196
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
22197
|
+
throw new Error(`Failed to create supersedes edge: ${message}`);
|
|
22198
|
+
}
|
|
22199
|
+
return {
|
|
22200
|
+
success: true,
|
|
22201
|
+
oldId,
|
|
22202
|
+
newId,
|
|
22203
|
+
edgeType: "supersedes"
|
|
22204
|
+
};
|
|
22205
|
+
}
|
|
22206
|
+
async function detectSupersession(projectRoot, newEntry) {
|
|
22207
|
+
try {
|
|
22208
|
+
await getBrainDb(projectRoot);
|
|
22209
|
+
const nativeDb = getBrainNativeDb();
|
|
22210
|
+
if (!nativeDb) return [];
|
|
22211
|
+
const newLocation = await locateEntry(projectRoot, newEntry.id);
|
|
22212
|
+
if (!newLocation) return [];
|
|
22213
|
+
const { tableConfig } = newLocation;
|
|
22214
|
+
const existing = typedAll(
|
|
22215
|
+
nativeDb.prepare(`
|
|
22216
|
+
SELECT id, COALESCE(${tableConfig.textCol}, '') AS text,
|
|
22217
|
+
created_at, quality_score
|
|
22218
|
+
FROM ${tableConfig.table}
|
|
22219
|
+
WHERE invalid_at IS NULL
|
|
22220
|
+
AND id != ?
|
|
22221
|
+
ORDER BY created_at DESC
|
|
22222
|
+
LIMIT 200
|
|
22223
|
+
`),
|
|
22224
|
+
newEntry.id
|
|
22225
|
+
);
|
|
22226
|
+
if (existing.length === 0) return [];
|
|
22227
|
+
const candidates = [];
|
|
22228
|
+
for (const row of existing) {
|
|
22229
|
+
if (row.created_at >= newEntry.createdAt) continue;
|
|
22230
|
+
const { similarity, shared } = keywordSimilarity(newEntry.text, row.text);
|
|
22231
|
+
if (similarity >= KEYWORD_OVERLAP_THRESHOLD) {
|
|
22232
|
+
candidates.push({
|
|
22233
|
+
existingId: row.id,
|
|
22234
|
+
similarity,
|
|
22235
|
+
table: tableConfig.table,
|
|
22236
|
+
sharedKeywords: shared.slice(0, 10)
|
|
22237
|
+
});
|
|
22238
|
+
}
|
|
22239
|
+
}
|
|
22240
|
+
candidates.sort((a, b2) => b2.similarity - a.similarity);
|
|
22241
|
+
return candidates;
|
|
22242
|
+
} catch (err) {
|
|
22243
|
+
console.warn("[temporal-supersession] detectSupersession failed:", err);
|
|
22244
|
+
return [];
|
|
22245
|
+
}
|
|
22246
|
+
}
|
|
22247
|
+
var KEYWORD_OVERLAP_THRESHOLD, MIN_SHARED_KEYWORDS, STOP_WORDS, SUPERSEDABLE_TABLES;
|
|
22248
|
+
var init_temporal_supersession = __esm({
|
|
22249
|
+
"packages/core/src/memory/temporal-supersession.ts"() {
|
|
22250
|
+
"use strict";
|
|
22251
|
+
init_brain_sqlite();
|
|
22252
|
+
init_typed_query();
|
|
22253
|
+
KEYWORD_OVERLAP_THRESHOLD = 0.8;
|
|
22254
|
+
MIN_SHARED_KEYWORDS = 3;
|
|
22255
|
+
STOP_WORDS = /* @__PURE__ */ new Set([
|
|
22256
|
+
"the",
|
|
22257
|
+
"a",
|
|
22258
|
+
"an",
|
|
22259
|
+
"is",
|
|
22260
|
+
"are",
|
|
22261
|
+
"was",
|
|
22262
|
+
"were",
|
|
22263
|
+
"be",
|
|
22264
|
+
"been",
|
|
22265
|
+
"being",
|
|
22266
|
+
"have",
|
|
22267
|
+
"has",
|
|
22268
|
+
"had",
|
|
22269
|
+
"do",
|
|
22270
|
+
"does",
|
|
22271
|
+
"did",
|
|
22272
|
+
"will",
|
|
22273
|
+
"would",
|
|
22274
|
+
"could",
|
|
22275
|
+
"should",
|
|
22276
|
+
"may",
|
|
22277
|
+
"might",
|
|
22278
|
+
"shall",
|
|
22279
|
+
"can",
|
|
22280
|
+
"to",
|
|
22281
|
+
"of",
|
|
22282
|
+
"in",
|
|
22283
|
+
"for",
|
|
22284
|
+
"on",
|
|
22285
|
+
"with",
|
|
22286
|
+
"at",
|
|
22287
|
+
"by",
|
|
22288
|
+
"from",
|
|
22289
|
+
"as",
|
|
22290
|
+
"into",
|
|
22291
|
+
"through",
|
|
22292
|
+
"and",
|
|
22293
|
+
"but",
|
|
22294
|
+
"or",
|
|
22295
|
+
"nor",
|
|
22296
|
+
"so",
|
|
22297
|
+
"yet",
|
|
22298
|
+
"this",
|
|
22299
|
+
"that",
|
|
22300
|
+
"these",
|
|
22301
|
+
"those",
|
|
22302
|
+
"it",
|
|
22303
|
+
"its",
|
|
22304
|
+
"not",
|
|
22305
|
+
"no"
|
|
22306
|
+
]);
|
|
22307
|
+
SUPERSEDABLE_TABLES = [
|
|
22308
|
+
{ table: "brain_decisions", textCol: "decision", type: "decision" },
|
|
22309
|
+
{ table: "brain_learnings", textCol: "insight", type: "learning" },
|
|
22310
|
+
{ table: "brain_patterns", textCol: "pattern", type: "pattern" },
|
|
22311
|
+
{ table: "brain_observations", textCol: "narrative", type: "observation" }
|
|
22312
|
+
];
|
|
22313
|
+
}
|
|
22314
|
+
});
|
|
22315
|
+
|
|
22112
22316
|
// packages/core/src/memory/patterns.ts
|
|
22113
22317
|
var patterns_exports = {};
|
|
22114
22318
|
__export(patterns_exports, {
|
|
@@ -22206,6 +22410,22 @@ async function storePattern(projectRoot, params) {
|
|
|
22206
22410
|
{ type: saved.type, impact: saved.impact ?? void 0 }
|
|
22207
22411
|
).catch(() => {
|
|
22208
22412
|
});
|
|
22413
|
+
detectSupersession(projectRoot, {
|
|
22414
|
+
id: saved.id,
|
|
22415
|
+
text: saved.pattern + " " + saved.context,
|
|
22416
|
+
createdAt: saved.extractedAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
22417
|
+
}).then((candidates) => {
|
|
22418
|
+
for (const candidate of candidates) {
|
|
22419
|
+
supersedeMemory(
|
|
22420
|
+
projectRoot,
|
|
22421
|
+
candidate.existingId,
|
|
22422
|
+
saved.id,
|
|
22423
|
+
"auto:pattern-supersedes \u2014 high overlap detected at store time"
|
|
22424
|
+
).catch(() => {
|
|
22425
|
+
});
|
|
22426
|
+
}
|
|
22427
|
+
}).catch(() => {
|
|
22428
|
+
});
|
|
22209
22429
|
return {
|
|
22210
22430
|
...saved,
|
|
22211
22431
|
examples: JSON.parse(saved.examplesJson || "[]")
|
|
@@ -22262,6 +22482,7 @@ var init_patterns = __esm({
|
|
|
22262
22482
|
init_brain_accessor();
|
|
22263
22483
|
init_graph_auto_populate();
|
|
22264
22484
|
init_quality_scoring();
|
|
22485
|
+
init_temporal_supersession();
|
|
22265
22486
|
}
|
|
22266
22487
|
});
|
|
22267
22488
|
|
|
@@ -22353,6 +22574,22 @@ async function storeLearning(projectRoot, params) {
|
|
|
22353
22574
|
{ source: saved.source, confidence: saved.confidence, actionable: saved.actionable }
|
|
22354
22575
|
).catch(() => {
|
|
22355
22576
|
});
|
|
22577
|
+
detectSupersession(projectRoot, {
|
|
22578
|
+
id: saved.id,
|
|
22579
|
+
text: saved.insight,
|
|
22580
|
+
createdAt: saved.createdAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
22581
|
+
}).then((candidates) => {
|
|
22582
|
+
for (const candidate of candidates) {
|
|
22583
|
+
supersedeMemory(
|
|
22584
|
+
projectRoot,
|
|
22585
|
+
candidate.existingId,
|
|
22586
|
+
saved.id,
|
|
22587
|
+
"auto:learning-supersedes \u2014 high overlap detected at store time"
|
|
22588
|
+
).catch(() => {
|
|
22589
|
+
});
|
|
22590
|
+
}
|
|
22591
|
+
}).catch(() => {
|
|
22592
|
+
});
|
|
22356
22593
|
return {
|
|
22357
22594
|
...saved,
|
|
22358
22595
|
applicableTypes: JSON.parse(saved.applicableTypesJson || "[]")
|
|
@@ -22413,6 +22650,7 @@ var init_learnings = __esm({
|
|
|
22413
22650
|
init_brain_accessor();
|
|
22414
22651
|
init_graph_auto_populate();
|
|
22415
22652
|
init_quality_scoring();
|
|
22653
|
+
init_temporal_supersession();
|
|
22416
22654
|
}
|
|
22417
22655
|
});
|
|
22418
22656
|
|
|
@@ -22451,16 +22689,6 @@ var init_mvi_helpers = __esm({
|
|
|
22451
22689
|
}
|
|
22452
22690
|
});
|
|
22453
22691
|
|
|
22454
|
-
// packages/core/src/store/typed-query.ts
|
|
22455
|
-
function typedAll(stmt, ...params) {
|
|
22456
|
-
return stmt.all(...params);
|
|
22457
|
-
}
|
|
22458
|
-
var init_typed_query = __esm({
|
|
22459
|
-
"packages/core/src/store/typed-query.ts"() {
|
|
22460
|
-
"use strict";
|
|
22461
|
-
}
|
|
22462
|
-
});
|
|
22463
|
-
|
|
22464
22692
|
// packages/core/src/memory/brain-similarity.ts
|
|
22465
22693
|
function parseIdPrefix(id) {
|
|
22466
22694
|
if (id.startsWith("D-") || /^D\d/.test(id)) return "decision";
|
|
@@ -24245,6 +24473,22 @@ async function storeDecision(projectRoot, params) {
|
|
|
24245
24473
|
}
|
|
24246
24474
|
} catch {
|
|
24247
24475
|
}
|
|
24476
|
+
detectSupersession(projectRoot, {
|
|
24477
|
+
id: saved.id,
|
|
24478
|
+
text: saved.decision + " " + saved.rationale,
|
|
24479
|
+
createdAt: saved.createdAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
24480
|
+
}).then((candidates) => {
|
|
24481
|
+
for (const candidate of candidates) {
|
|
24482
|
+
supersedeMemory(
|
|
24483
|
+
projectRoot,
|
|
24484
|
+
candidate.existingId,
|
|
24485
|
+
saved.id,
|
|
24486
|
+
"auto:decision-supersedes \u2014 high overlap detected at store time"
|
|
24487
|
+
).catch(() => {
|
|
24488
|
+
});
|
|
24489
|
+
}
|
|
24490
|
+
}).catch(() => {
|
|
24491
|
+
});
|
|
24248
24492
|
return saved;
|
|
24249
24493
|
}
|
|
24250
24494
|
async function recallDecision(projectRoot, id) {
|
|
@@ -24297,6 +24541,7 @@ var init_decisions2 = __esm({
|
|
|
24297
24541
|
init_sqlite2();
|
|
24298
24542
|
init_graph_auto_populate();
|
|
24299
24543
|
init_quality_scoring();
|
|
24544
|
+
init_temporal_supersession();
|
|
24300
24545
|
}
|
|
24301
24546
|
});
|
|
24302
24547
|
|
|
@@ -45369,11 +45614,11 @@ var brain_consolidator_exports = {};
|
|
|
45369
45614
|
__export(brain_consolidator_exports, {
|
|
45370
45615
|
detectContradictions: () => detectContradictions
|
|
45371
45616
|
});
|
|
45372
|
-
function
|
|
45617
|
+
function extractKeywords2(text3) {
|
|
45373
45618
|
const words = text3.toLowerCase().replace(/[^a-z0-9\s\-_]/g, " ").split(/\s+/);
|
|
45374
45619
|
const keywords = /* @__PURE__ */ new Set();
|
|
45375
45620
|
for (const w2 of words) {
|
|
45376
|
-
if (w2.length >= 4 && !
|
|
45621
|
+
if (w2.length >= 4 && !STOP_WORDS2.has(w2)) {
|
|
45377
45622
|
keywords.add(w2);
|
|
45378
45623
|
}
|
|
45379
45624
|
}
|
|
@@ -45422,7 +45667,7 @@ async function detectContradictions(projectRoot) {
|
|
|
45422
45667
|
const keywordMap = /* @__PURE__ */ new Map();
|
|
45423
45668
|
const negationMap = /* @__PURE__ */ new Map();
|
|
45424
45669
|
for (const entry of entries) {
|
|
45425
|
-
keywordMap.set(entry.id,
|
|
45670
|
+
keywordMap.set(entry.id, extractKeywords2(entry.text));
|
|
45426
45671
|
negationMap.set(entry.id, findNegationMarkers(entry.text));
|
|
45427
45672
|
}
|
|
45428
45673
|
for (let i = 0; i < entries.length; i++) {
|
|
@@ -45436,7 +45681,7 @@ async function detectContradictions(projectRoot) {
|
|
|
45436
45681
|
const keywordsB = keywordMap.get(entryB.id);
|
|
45437
45682
|
const negationsB = negationMap.get(entryB.id);
|
|
45438
45683
|
const shared = keywordIntersection(keywordsA, keywordsB);
|
|
45439
|
-
if (shared.length <
|
|
45684
|
+
if (shared.length < MIN_SHARED_KEYWORDS2) continue;
|
|
45440
45685
|
const negationsOnlyInA = negationsA.filter((m2) => !negationsB.includes(m2));
|
|
45441
45686
|
const negationsOnlyInB = negationsB.filter((m2) => !negationsA.includes(m2));
|
|
45442
45687
|
const negationFlip = negationsOnlyInA.length > 0 || negationsOnlyInB.length > 0;
|
|
@@ -45454,8 +45699,8 @@ async function detectContradictions(projectRoot) {
|
|
|
45454
45699
|
sharedKeywords: shared.slice(0, 10),
|
|
45455
45700
|
negationMarkers: negMarkers.slice(0, 5)
|
|
45456
45701
|
});
|
|
45457
|
-
const nodeA =
|
|
45458
|
-
const nodeB =
|
|
45702
|
+
const nodeA = buildNodeId2(table, entryA.id);
|
|
45703
|
+
const nodeB = buildNodeId2(table, entryB.id);
|
|
45459
45704
|
try {
|
|
45460
45705
|
nativeDb.prepare(`
|
|
45461
45706
|
INSERT OR IGNORE INTO brain_page_edges
|
|
@@ -45484,7 +45729,7 @@ async function detectContradictions(projectRoot) {
|
|
|
45484
45729
|
}
|
|
45485
45730
|
return results;
|
|
45486
45731
|
}
|
|
45487
|
-
function
|
|
45732
|
+
function buildNodeId2(table, entryId) {
|
|
45488
45733
|
const typeMap = {
|
|
45489
45734
|
brain_observations: "observation",
|
|
45490
45735
|
brain_learnings: "learning",
|
|
@@ -45494,13 +45739,13 @@ function buildNodeId(table, entryId) {
|
|
|
45494
45739
|
const type = typeMap[table] ?? "entry";
|
|
45495
45740
|
return `${type}:${entryId}`;
|
|
45496
45741
|
}
|
|
45497
|
-
var
|
|
45742
|
+
var MIN_SHARED_KEYWORDS2, NEGATION_MARKERS, STOP_WORDS2;
|
|
45498
45743
|
var init_brain_consolidator = __esm({
|
|
45499
45744
|
"packages/core/src/memory/brain-consolidator.ts"() {
|
|
45500
45745
|
"use strict";
|
|
45501
45746
|
init_brain_sqlite();
|
|
45502
45747
|
init_typed_query();
|
|
45503
|
-
|
|
45748
|
+
MIN_SHARED_KEYWORDS2 = 3;
|
|
45504
45749
|
NEGATION_MARKERS = [
|
|
45505
45750
|
"not",
|
|
45506
45751
|
"never",
|
|
@@ -45521,7 +45766,7 @@ var init_brain_consolidator = __esm({
|
|
|
45521
45766
|
"undone",
|
|
45522
45767
|
"superseded"
|
|
45523
45768
|
];
|
|
45524
|
-
|
|
45769
|
+
STOP_WORDS2 = /* @__PURE__ */ new Set([
|
|
45525
45770
|
"the",
|
|
45526
45771
|
"a",
|
|
45527
45772
|
"an",
|
|
@@ -45576,6 +45821,390 @@ var init_brain_consolidator = __esm({
|
|
|
45576
45821
|
}
|
|
45577
45822
|
});
|
|
45578
45823
|
|
|
45824
|
+
// packages/core/src/memory/graph-memory-bridge.ts
|
|
45825
|
+
var graph_memory_bridge_exports = {};
|
|
45826
|
+
__export(graph_memory_bridge_exports, {
|
|
45827
|
+
autoLinkMemories: () => autoLinkMemories,
|
|
45828
|
+
linkMemoryToCode: () => linkMemoryToCode,
|
|
45829
|
+
listCodeLinks: () => listCodeLinks,
|
|
45830
|
+
queryCodeForMemory: () => queryCodeForMemory,
|
|
45831
|
+
queryMemoriesForCode: () => queryMemoriesForCode
|
|
45832
|
+
});
|
|
45833
|
+
function extractFilePaths(text3) {
|
|
45834
|
+
const paths = /* @__PURE__ */ new Set();
|
|
45835
|
+
for (const m2 of text3.matchAll(FILE_PATH_PATTERN)) {
|
|
45836
|
+
const p2 = m2[1];
|
|
45837
|
+
if (p2) paths.add(p2);
|
|
45838
|
+
}
|
|
45839
|
+
return Array.from(paths);
|
|
45840
|
+
}
|
|
45841
|
+
function extractSymbolCandidates(text3) {
|
|
45842
|
+
const syms = /* @__PURE__ */ new Set();
|
|
45843
|
+
for (const m2 of text3.matchAll(SYMBOL_PATTERN)) {
|
|
45844
|
+
const s3 = m2[1];
|
|
45845
|
+
if (s3 && s3.length >= 4 && !SYMBOL_STOP_WORDS.has(s3.toLowerCase())) {
|
|
45846
|
+
syms.add(s3);
|
|
45847
|
+
}
|
|
45848
|
+
}
|
|
45849
|
+
return Array.from(syms);
|
|
45850
|
+
}
|
|
45851
|
+
function metadataText(metaJson) {
|
|
45852
|
+
if (!metaJson) return "";
|
|
45853
|
+
try {
|
|
45854
|
+
const obj = JSON.parse(metaJson);
|
|
45855
|
+
return Object.values(obj).filter((v2) => typeof v2 === "string").join(" ");
|
|
45856
|
+
} catch {
|
|
45857
|
+
return "";
|
|
45858
|
+
}
|
|
45859
|
+
}
|
|
45860
|
+
async function linkMemoryToCode(projectRoot, memoryId, codeSymbol) {
|
|
45861
|
+
try {
|
|
45862
|
+
const brainDb = await getBrainDb(projectRoot);
|
|
45863
|
+
await getNexusDb();
|
|
45864
|
+
const nexusNative = getNexusNativeDb();
|
|
45865
|
+
if (!nexusNative) return false;
|
|
45866
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(codeSymbol);
|
|
45867
|
+
if (!nexusNode) return false;
|
|
45868
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
45869
|
+
const idParts = memoryId.split(":");
|
|
45870
|
+
const nodeType = idParts[0] ?? "observation";
|
|
45871
|
+
await brainDb.insert(brainPageNodes).values({
|
|
45872
|
+
id: memoryId,
|
|
45873
|
+
nodeType,
|
|
45874
|
+
label: memoryId,
|
|
45875
|
+
qualityScore: 0.5,
|
|
45876
|
+
contentHash: null,
|
|
45877
|
+
lastActivityAt: now2,
|
|
45878
|
+
createdAt: now2,
|
|
45879
|
+
updatedAt: now2
|
|
45880
|
+
}).onConflictDoUpdate({
|
|
45881
|
+
target: brainPageNodes.id,
|
|
45882
|
+
set: { lastActivityAt: now2, updatedAt: now2 }
|
|
45883
|
+
});
|
|
45884
|
+
await brainDb.insert(brainPageEdges).values({
|
|
45885
|
+
fromId: memoryId,
|
|
45886
|
+
toId: codeSymbol,
|
|
45887
|
+
edgeType: "code_reference",
|
|
45888
|
+
weight: 1,
|
|
45889
|
+
provenance: "manual",
|
|
45890
|
+
createdAt: now2
|
|
45891
|
+
}).onConflictDoNothing();
|
|
45892
|
+
return true;
|
|
45893
|
+
} catch (err) {
|
|
45894
|
+
console.warn("[graph-memory-bridge] linkMemoryToCode failed:", err);
|
|
45895
|
+
return false;
|
|
45896
|
+
}
|
|
45897
|
+
}
|
|
45898
|
+
async function autoLinkMemories(projectRoot) {
|
|
45899
|
+
const result = { scanned: 0, linked: 0, alreadyLinked: 0, links: [] };
|
|
45900
|
+
try {
|
|
45901
|
+
await getBrainDb(projectRoot);
|
|
45902
|
+
const brainNative = getBrainNativeDb();
|
|
45903
|
+
await getNexusDb();
|
|
45904
|
+
const nexusNative = getNexusNativeDb();
|
|
45905
|
+
if (!brainNative || !nexusNative) return result;
|
|
45906
|
+
const brainNodes = typedAll(
|
|
45907
|
+
brainNative.prepare(`
|
|
45908
|
+
SELECT id, node_type, label, quality_score, metadata_json
|
|
45909
|
+
FROM brain_page_nodes
|
|
45910
|
+
WHERE node_type IN ('observation', 'decision', 'pattern', 'learning')
|
|
45911
|
+
AND quality_score >= 0.3
|
|
45912
|
+
ORDER BY quality_score DESC
|
|
45913
|
+
LIMIT 500
|
|
45914
|
+
`)
|
|
45915
|
+
);
|
|
45916
|
+
result.scanned = brainNodes.length;
|
|
45917
|
+
if (brainNodes.length === 0) return result;
|
|
45918
|
+
const nexusNodes2 = typedAll(
|
|
45919
|
+
nexusNative.prepare(`
|
|
45920
|
+
SELECT id, label, name, file_path, kind
|
|
45921
|
+
FROM nexus_nodes
|
|
45922
|
+
WHERE kind NOT IN ('community', 'process', 'folder')
|
|
45923
|
+
LIMIT 20000
|
|
45924
|
+
`)
|
|
45925
|
+
);
|
|
45926
|
+
if (nexusNodes2.length === 0) return result;
|
|
45927
|
+
const byFilePath = /* @__PURE__ */ new Map();
|
|
45928
|
+
const byNameExact = /* @__PURE__ */ new Map();
|
|
45929
|
+
const byNameLower = /* @__PURE__ */ new Map();
|
|
45930
|
+
for (const node of nexusNodes2) {
|
|
45931
|
+
if (node.file_path) {
|
|
45932
|
+
const fp = node.file_path.toLowerCase();
|
|
45933
|
+
const existing = byFilePath.get(fp) ?? [];
|
|
45934
|
+
existing.push(node);
|
|
45935
|
+
byFilePath.set(fp, existing);
|
|
45936
|
+
}
|
|
45937
|
+
if (node.name) {
|
|
45938
|
+
const exact = byNameExact.get(node.name) ?? [];
|
|
45939
|
+
exact.push(node);
|
|
45940
|
+
byNameExact.set(node.name, exact);
|
|
45941
|
+
const lower = node.name.toLowerCase();
|
|
45942
|
+
const fuzzy = byNameLower.get(lower) ?? [];
|
|
45943
|
+
fuzzy.push(node);
|
|
45944
|
+
byNameLower.set(lower, fuzzy);
|
|
45945
|
+
}
|
|
45946
|
+
}
|
|
45947
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
45948
|
+
const existingEdges = /* @__PURE__ */ new Set();
|
|
45949
|
+
const rawEdges = typedAll(
|
|
45950
|
+
brainNative.prepare(`
|
|
45951
|
+
SELECT from_id, to_id FROM brain_page_edges WHERE edge_type = 'code_reference'
|
|
45952
|
+
`)
|
|
45953
|
+
);
|
|
45954
|
+
for (const e of rawEdges) {
|
|
45955
|
+
existingEdges.add(`${e.from_id}|${e.to_id}`);
|
|
45956
|
+
}
|
|
45957
|
+
for (const brainNode of brainNodes) {
|
|
45958
|
+
const corpus = `${brainNode.label} ${metadataText(brainNode.metadata_json)}`;
|
|
45959
|
+
const filePaths = extractFilePaths(corpus);
|
|
45960
|
+
const symbolCandidates = extractSymbolCandidates(corpus);
|
|
45961
|
+
const candidates = [];
|
|
45962
|
+
for (const fp of filePaths) {
|
|
45963
|
+
const matches = byFilePath.get(fp.toLowerCase());
|
|
45964
|
+
if (matches) {
|
|
45965
|
+
for (const n of matches) {
|
|
45966
|
+
candidates.push({ nexusNode: n, strategy: "exact-file", weight: 1 });
|
|
45967
|
+
}
|
|
45968
|
+
}
|
|
45969
|
+
}
|
|
45970
|
+
for (const sym of symbolCandidates) {
|
|
45971
|
+
const exactMatches = byNameExact.get(sym);
|
|
45972
|
+
if (exactMatches) {
|
|
45973
|
+
for (const n of exactMatches) {
|
|
45974
|
+
candidates.push({ nexusNode: n, strategy: "exact-symbol", weight: 1 });
|
|
45975
|
+
}
|
|
45976
|
+
}
|
|
45977
|
+
}
|
|
45978
|
+
const exactSymSet = new Set(
|
|
45979
|
+
symbolCandidates.flatMap((s3) => byNameExact.get(s3) ?? []).map((n) => n.id)
|
|
45980
|
+
);
|
|
45981
|
+
for (const sym of symbolCandidates) {
|
|
45982
|
+
if (sym.length < 5) continue;
|
|
45983
|
+
const lower = sym.toLowerCase();
|
|
45984
|
+
const fuzzyMatches = byNameLower.get(lower);
|
|
45985
|
+
if (fuzzyMatches) {
|
|
45986
|
+
for (const n of fuzzyMatches) {
|
|
45987
|
+
if (!exactSymSet.has(n.id)) {
|
|
45988
|
+
candidates.push({ nexusNode: n, strategy: "fuzzy-symbol", weight: 0.6 });
|
|
45989
|
+
}
|
|
45990
|
+
}
|
|
45991
|
+
}
|
|
45992
|
+
}
|
|
45993
|
+
const bestByNexusId = /* @__PURE__ */ new Map();
|
|
45994
|
+
for (const c of candidates) {
|
|
45995
|
+
const existing = bestByNexusId.get(c.nexusNode.id);
|
|
45996
|
+
if (!existing || c.weight > existing.weight) {
|
|
45997
|
+
bestByNexusId.set(c.nexusNode.id, c);
|
|
45998
|
+
}
|
|
45999
|
+
}
|
|
46000
|
+
const sortedCandidates = Array.from(bestByNexusId.values()).sort((a, b2) => b2.weight - a.weight).slice(0, 10);
|
|
46001
|
+
for (const { nexusNode, strategy, weight } of sortedCandidates) {
|
|
46002
|
+
const edgeKey = `${brainNode.id}|${nexusNode.id}`;
|
|
46003
|
+
if (existingEdges.has(edgeKey)) {
|
|
46004
|
+
result.alreadyLinked++;
|
|
46005
|
+
continue;
|
|
46006
|
+
}
|
|
46007
|
+
brainNative.prepare(`
|
|
46008
|
+
INSERT OR IGNORE INTO brain_page_nodes
|
|
46009
|
+
(id, node_type, label, quality_score, content_hash, metadata_json, last_activity_at, created_at, updated_at)
|
|
46010
|
+
VALUES (?, ?, ?, ?, NULL, NULL, ?, ?, ?)
|
|
46011
|
+
`).run(
|
|
46012
|
+
brainNode.id,
|
|
46013
|
+
brainNode.node_type,
|
|
46014
|
+
brainNode.label,
|
|
46015
|
+
brainNode.quality_score,
|
|
46016
|
+
now2,
|
|
46017
|
+
now2,
|
|
46018
|
+
now2
|
|
46019
|
+
);
|
|
46020
|
+
try {
|
|
46021
|
+
brainNative.prepare(`
|
|
46022
|
+
INSERT OR IGNORE INTO brain_page_edges
|
|
46023
|
+
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
46024
|
+
VALUES (?, ?, 'code_reference', ?, ?, ?)
|
|
46025
|
+
`).run(brainNode.id, nexusNode.id, weight, `auto:${strategy}`, now2);
|
|
46026
|
+
existingEdges.add(edgeKey);
|
|
46027
|
+
result.linked++;
|
|
46028
|
+
result.links.push({
|
|
46029
|
+
brainNodeId: brainNode.id,
|
|
46030
|
+
nexusNodeId: nexusNode.id,
|
|
46031
|
+
nexusLabel: nexusNode.label,
|
|
46032
|
+
matchStrategy: strategy,
|
|
46033
|
+
weight
|
|
46034
|
+
});
|
|
46035
|
+
} catch (edgeErr) {
|
|
46036
|
+
console.warn("[graph-memory-bridge] edge insert failed:", edgeErr);
|
|
46037
|
+
}
|
|
46038
|
+
}
|
|
46039
|
+
}
|
|
46040
|
+
} catch (err) {
|
|
46041
|
+
console.warn("[graph-memory-bridge] autoLinkMemories failed:", err);
|
|
46042
|
+
}
|
|
46043
|
+
return result;
|
|
46044
|
+
}
|
|
46045
|
+
async function queryMemoriesForCode(projectRoot, symbol2) {
|
|
46046
|
+
const result = { nexusNodeId: symbol2, memories: [] };
|
|
46047
|
+
try {
|
|
46048
|
+
await getBrainDb(projectRoot);
|
|
46049
|
+
const brainNative = getBrainNativeDb();
|
|
46050
|
+
if (!brainNative) return result;
|
|
46051
|
+
const rows = typedAll(
|
|
46052
|
+
brainNative.prepare(`
|
|
46053
|
+
SELECT n.id, n.node_type, n.label, n.quality_score,
|
|
46054
|
+
e.weight, e.provenance
|
|
46055
|
+
FROM brain_page_edges e
|
|
46056
|
+
JOIN brain_page_nodes n ON n.id = e.from_id
|
|
46057
|
+
WHERE e.to_id = ?
|
|
46058
|
+
AND e.edge_type = 'code_reference'
|
|
46059
|
+
ORDER BY e.weight DESC, n.quality_score DESC
|
|
46060
|
+
LIMIT 50
|
|
46061
|
+
`),
|
|
46062
|
+
symbol2
|
|
46063
|
+
);
|
|
46064
|
+
result.memories = rows.map((r) => ({
|
|
46065
|
+
nodeId: r.id,
|
|
46066
|
+
nodeType: r.node_type,
|
|
46067
|
+
label: r.label,
|
|
46068
|
+
qualityScore: r.quality_score,
|
|
46069
|
+
edgeWeight: r.weight,
|
|
46070
|
+
matchStrategy: r.provenance?.replace("auto:", "") ?? "manual"
|
|
46071
|
+
}));
|
|
46072
|
+
} catch (err) {
|
|
46073
|
+
console.warn("[graph-memory-bridge] queryMemoriesForCode failed:", err);
|
|
46074
|
+
}
|
|
46075
|
+
return result;
|
|
46076
|
+
}
|
|
46077
|
+
async function queryCodeForMemory(projectRoot, memoryId) {
|
|
46078
|
+
const result = { brainNodeId: memoryId, codeNodes: [] };
|
|
46079
|
+
try {
|
|
46080
|
+
await getBrainDb(projectRoot);
|
|
46081
|
+
const brainNative = getBrainNativeDb();
|
|
46082
|
+
await getNexusDb();
|
|
46083
|
+
const nexusNative = getNexusNativeDb();
|
|
46084
|
+
if (!brainNative || !nexusNative) return result;
|
|
46085
|
+
const brainEdges = typedAll(
|
|
46086
|
+
brainNative.prepare(`
|
|
46087
|
+
SELECT to_id, weight, provenance
|
|
46088
|
+
FROM brain_page_edges
|
|
46089
|
+
WHERE from_id = ?
|
|
46090
|
+
AND edge_type = 'code_reference'
|
|
46091
|
+
ORDER BY weight DESC
|
|
46092
|
+
LIMIT 50
|
|
46093
|
+
`),
|
|
46094
|
+
memoryId
|
|
46095
|
+
);
|
|
46096
|
+
if (brainEdges.length === 0) return result;
|
|
46097
|
+
for (const edge of brainEdges) {
|
|
46098
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(edge.to_id);
|
|
46099
|
+
if (nexusNode) {
|
|
46100
|
+
result.codeNodes.push({
|
|
46101
|
+
nexusNodeId: nexusNode.id,
|
|
46102
|
+
label: nexusNode.label,
|
|
46103
|
+
filePath: nexusNode.file_path,
|
|
46104
|
+
kind: nexusNode.kind,
|
|
46105
|
+
edgeWeight: edge.weight,
|
|
46106
|
+
matchStrategy: edge.provenance?.replace("auto:", "") ?? "manual"
|
|
46107
|
+
});
|
|
46108
|
+
}
|
|
46109
|
+
}
|
|
46110
|
+
} catch (err) {
|
|
46111
|
+
console.warn("[graph-memory-bridge] queryCodeForMemory failed:", err);
|
|
46112
|
+
}
|
|
46113
|
+
return result;
|
|
46114
|
+
}
|
|
46115
|
+
async function listCodeLinks(projectRoot, limit = 100) {
|
|
46116
|
+
const entries = [];
|
|
46117
|
+
try {
|
|
46118
|
+
await getBrainDb(projectRoot);
|
|
46119
|
+
const brainNative = getBrainNativeDb();
|
|
46120
|
+
await getNexusDb();
|
|
46121
|
+
const nexusNative = getNexusNativeDb();
|
|
46122
|
+
if (!brainNative || !nexusNative) return entries;
|
|
46123
|
+
const rows = typedAll(
|
|
46124
|
+
brainNative.prepare(`
|
|
46125
|
+
SELECT e.from_id, e.to_id, e.weight, e.created_at,
|
|
46126
|
+
n.node_type, n.label
|
|
46127
|
+
FROM brain_page_edges e
|
|
46128
|
+
JOIN brain_page_nodes n ON n.id = e.from_id
|
|
46129
|
+
WHERE e.edge_type = 'code_reference'
|
|
46130
|
+
ORDER BY e.weight DESC, e.created_at DESC
|
|
46131
|
+
LIMIT ?
|
|
46132
|
+
`),
|
|
46133
|
+
limit
|
|
46134
|
+
);
|
|
46135
|
+
for (const row of rows) {
|
|
46136
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(row.to_id);
|
|
46137
|
+
entries.push({
|
|
46138
|
+
brainNodeId: row.from_id,
|
|
46139
|
+
brainNodeType: row.node_type,
|
|
46140
|
+
brainNodeLabel: row.label,
|
|
46141
|
+
nexusNodeId: row.to_id,
|
|
46142
|
+
nexusNodeLabel: nexusNode?.label ?? row.to_id,
|
|
46143
|
+
filePath: nexusNode?.file_path ?? null,
|
|
46144
|
+
kind: nexusNode?.kind ?? "unknown",
|
|
46145
|
+
weight: row.weight,
|
|
46146
|
+
createdAt: row.created_at
|
|
46147
|
+
});
|
|
46148
|
+
}
|
|
46149
|
+
} catch (err) {
|
|
46150
|
+
console.warn("[graph-memory-bridge] listCodeLinks failed:", err);
|
|
46151
|
+
}
|
|
46152
|
+
return entries;
|
|
46153
|
+
}
|
|
46154
|
+
var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
|
|
46155
|
+
var init_graph_memory_bridge = __esm({
|
|
46156
|
+
"packages/core/src/memory/graph-memory-bridge.ts"() {
|
|
46157
|
+
"use strict";
|
|
46158
|
+
init_brain_schema();
|
|
46159
|
+
init_brain_sqlite();
|
|
46160
|
+
init_nexus_sqlite();
|
|
46161
|
+
init_typed_query();
|
|
46162
|
+
FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
|
|
46163
|
+
SYMBOL_PATTERN = /\b([a-zA-Z_][a-zA-Z0-9_]*(?:[A-Z][a-zA-Z0-9_]*)+|[a-zA-Z_]{4,}[a-zA-Z0-9_]*)\b/g;
|
|
46164
|
+
SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
46165
|
+
"true",
|
|
46166
|
+
"false",
|
|
46167
|
+
"null",
|
|
46168
|
+
"undefined",
|
|
46169
|
+
"const",
|
|
46170
|
+
"async",
|
|
46171
|
+
"await",
|
|
46172
|
+
"return",
|
|
46173
|
+
"export",
|
|
46174
|
+
"import",
|
|
46175
|
+
"from",
|
|
46176
|
+
"type",
|
|
46177
|
+
"interface",
|
|
46178
|
+
"function",
|
|
46179
|
+
"class",
|
|
46180
|
+
"this",
|
|
46181
|
+
"super",
|
|
46182
|
+
"extends",
|
|
46183
|
+
"implements",
|
|
46184
|
+
"with",
|
|
46185
|
+
"that",
|
|
46186
|
+
"then",
|
|
46187
|
+
"when",
|
|
46188
|
+
"have",
|
|
46189
|
+
"been",
|
|
46190
|
+
"will",
|
|
46191
|
+
"should",
|
|
46192
|
+
"could",
|
|
46193
|
+
"would",
|
|
46194
|
+
"error",
|
|
46195
|
+
"result",
|
|
46196
|
+
"value",
|
|
46197
|
+
"data",
|
|
46198
|
+
"info",
|
|
46199
|
+
"note",
|
|
46200
|
+
"todo",
|
|
46201
|
+
"done",
|
|
46202
|
+
"fail",
|
|
46203
|
+
"pass"
|
|
46204
|
+
]);
|
|
46205
|
+
}
|
|
46206
|
+
});
|
|
46207
|
+
|
|
45579
46208
|
// packages/core/src/memory/brain-lifecycle.ts
|
|
45580
46209
|
var brain_lifecycle_exports = {};
|
|
45581
46210
|
__export(brain_lifecycle_exports, {
|
|
@@ -45609,11 +46238,11 @@ async function applyTemporalDecay(projectRoot, options) {
|
|
|
45609
46238
|
tablesProcessed: ["brain_learnings"]
|
|
45610
46239
|
};
|
|
45611
46240
|
}
|
|
45612
|
-
function
|
|
46241
|
+
function extractKeywords3(text3) {
|
|
45613
46242
|
const words = text3.toLowerCase().replace(/[^a-z0-9\s-]/g, "").split(/\s+/);
|
|
45614
46243
|
const keywords = /* @__PURE__ */ new Set();
|
|
45615
46244
|
for (const w2 of words) {
|
|
45616
|
-
if (w2.length >= 4 && !
|
|
46245
|
+
if (w2.length >= 4 && !STOP_WORDS3.has(w2)) {
|
|
45617
46246
|
keywords.add(w2);
|
|
45618
46247
|
}
|
|
45619
46248
|
}
|
|
@@ -45651,7 +46280,7 @@ async function consolidateMemories(projectRoot, options) {
|
|
|
45651
46280
|
}
|
|
45652
46281
|
const entries = oldObservations.map((obs) => ({
|
|
45653
46282
|
...obs,
|
|
45654
|
-
keywords:
|
|
46283
|
+
keywords: extractKeywords3(`${obs.title} ${obs.narrative ?? ""}`),
|
|
45655
46284
|
clustered: false
|
|
45656
46285
|
}));
|
|
45657
46286
|
const clusters = [];
|
|
@@ -45875,6 +46504,13 @@ async function runConsolidation(projectRoot) {
|
|
|
45875
46504
|
} catch (err) {
|
|
45876
46505
|
console.warn("[consolidation] Step 7 summary generation failed:", err);
|
|
45877
46506
|
}
|
|
46507
|
+
try {
|
|
46508
|
+
const { autoLinkMemories: autoLinkMemories2 } = await Promise.resolve().then(() => (init_graph_memory_bridge(), graph_memory_bridge_exports));
|
|
46509
|
+
const bridgeResult = await autoLinkMemories2(projectRoot);
|
|
46510
|
+
result.graphLinksCreated = bridgeResult.linked;
|
|
46511
|
+
} catch (err) {
|
|
46512
|
+
console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
|
|
46513
|
+
}
|
|
45878
46514
|
return result;
|
|
45879
46515
|
}
|
|
45880
46516
|
async function deduplicateByEmbedding(projectRoot) {
|
|
@@ -46053,13 +46689,13 @@ async function strengthenCoRetrievedEdges(projectRoot) {
|
|
|
46053
46689
|
}
|
|
46054
46690
|
return strengthened;
|
|
46055
46691
|
}
|
|
46056
|
-
var
|
|
46692
|
+
var STOP_WORDS3;
|
|
46057
46693
|
var init_brain_lifecycle = __esm({
|
|
46058
46694
|
"packages/core/src/memory/brain-lifecycle.ts"() {
|
|
46059
46695
|
"use strict";
|
|
46060
46696
|
init_brain_accessor();
|
|
46061
46697
|
init_typed_query();
|
|
46062
|
-
|
|
46698
|
+
STOP_WORDS3 = /* @__PURE__ */ new Set([
|
|
46063
46699
|
"the",
|
|
46064
46700
|
"a",
|
|
46065
46701
|
"an",
|
|
@@ -46664,6 +47300,358 @@ var init_session_hooks = __esm({
|
|
|
46664
47300
|
}
|
|
46665
47301
|
});
|
|
46666
47302
|
|
|
47303
|
+
// packages/core/src/memory/quality-feedback.ts
|
|
47304
|
+
var quality_feedback_exports = {};
|
|
47305
|
+
__export(quality_feedback_exports, {
|
|
47306
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
47307
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
47308
|
+
trackMemoryUsage: () => trackMemoryUsage
|
|
47309
|
+
});
|
|
47310
|
+
async function ensureUsageLogTable(projectRoot) {
|
|
47311
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47312
|
+
await getBrainDb2(projectRoot);
|
|
47313
|
+
const nativeDb = getBrainNativeDb2();
|
|
47314
|
+
if (!nativeDb) return;
|
|
47315
|
+
try {
|
|
47316
|
+
nativeDb.prepare(
|
|
47317
|
+
`CREATE TABLE IF NOT EXISTS brain_usage_log (
|
|
47318
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
47319
|
+
entry_id TEXT NOT NULL,
|
|
47320
|
+
task_id TEXT,
|
|
47321
|
+
used INTEGER NOT NULL DEFAULT 0,
|
|
47322
|
+
outcome TEXT NOT NULL DEFAULT 'unknown',
|
|
47323
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
47324
|
+
)`
|
|
47325
|
+
).run();
|
|
47326
|
+
nativeDb.prepare(
|
|
47327
|
+
`CREATE INDEX IF NOT EXISTS idx_brain_usage_log_entry_id
|
|
47328
|
+
ON brain_usage_log(entry_id)`
|
|
47329
|
+
).run();
|
|
47330
|
+
nativeDb.prepare(
|
|
47331
|
+
`CREATE INDEX IF NOT EXISTS idx_brain_usage_log_task_id
|
|
47332
|
+
ON brain_usage_log(task_id)`
|
|
47333
|
+
).run();
|
|
47334
|
+
} catch {
|
|
47335
|
+
}
|
|
47336
|
+
}
|
|
47337
|
+
async function ensurePruneCandidateColumn(projectRoot) {
|
|
47338
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47339
|
+
await getBrainDb2(projectRoot);
|
|
47340
|
+
const nativeDb = getBrainNativeDb2();
|
|
47341
|
+
if (!nativeDb) return;
|
|
47342
|
+
const tables = [
|
|
47343
|
+
"brain_decisions",
|
|
47344
|
+
"brain_patterns",
|
|
47345
|
+
"brain_learnings",
|
|
47346
|
+
"brain_observations"
|
|
47347
|
+
];
|
|
47348
|
+
for (const tbl of tables) {
|
|
47349
|
+
try {
|
|
47350
|
+
nativeDb.prepare(`ALTER TABLE ${tbl} ADD COLUMN prune_candidate INTEGER DEFAULT 0`).run();
|
|
47351
|
+
} catch {
|
|
47352
|
+
}
|
|
47353
|
+
}
|
|
47354
|
+
}
|
|
47355
|
+
async function trackMemoryUsage(projectRoot, memoryId, used, taskId, outcome = "unknown") {
|
|
47356
|
+
if (!memoryId?.trim()) return;
|
|
47357
|
+
await ensureUsageLogTable(projectRoot);
|
|
47358
|
+
const { getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47359
|
+
const nativeDb = getBrainNativeDb2();
|
|
47360
|
+
if (!nativeDb) return;
|
|
47361
|
+
const now2 = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
47362
|
+
try {
|
|
47363
|
+
nativeDb.prepare(
|
|
47364
|
+
`INSERT INTO brain_usage_log (entry_id, task_id, used, outcome, created_at)
|
|
47365
|
+
VALUES (?, ?, ?, ?, ?)`
|
|
47366
|
+
).run(memoryId, taskId ?? null, used ? 1 : 0, outcome, now2);
|
|
47367
|
+
} catch {
|
|
47368
|
+
}
|
|
47369
|
+
}
|
|
47370
|
+
function tableForId(id) {
|
|
47371
|
+
if (id.startsWith("D-") || /^D\d/.test(id)) return "brain_decisions";
|
|
47372
|
+
if (id.startsWith("P-") || /^P\d/.test(id)) return "brain_patterns";
|
|
47373
|
+
if (id.startsWith("L-") || /^L\d/.test(id)) return "brain_learnings";
|
|
47374
|
+
if (id.startsWith("O-") || id.startsWith("CM-") || /^O/.test(id)) return "brain_observations";
|
|
47375
|
+
return null;
|
|
47376
|
+
}
|
|
47377
|
+
function applyQualityDelta(nativeDb, table, id, delta, now2) {
|
|
47378
|
+
if (!nativeDb) return;
|
|
47379
|
+
try {
|
|
47380
|
+
nativeDb.prepare(
|
|
47381
|
+
`UPDATE ${table}
|
|
47382
|
+
SET quality_score = MAX(0.0, MIN(1.0, COALESCE(quality_score, 0.5) + ?)),
|
|
47383
|
+
updated_at = ?
|
|
47384
|
+
WHERE id = ?`
|
|
47385
|
+
).run(delta, now2, id);
|
|
47386
|
+
} catch {
|
|
47387
|
+
}
|
|
47388
|
+
}
|
|
47389
|
+
async function correlateOutcomes(projectRoot) {
|
|
47390
|
+
await ensureUsageLogTable(projectRoot);
|
|
47391
|
+
await ensurePruneCandidateColumn(projectRoot);
|
|
47392
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47393
|
+
await getBrainDb2(projectRoot);
|
|
47394
|
+
const nativeDb = getBrainNativeDb2();
|
|
47395
|
+
const ranAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
47396
|
+
if (!nativeDb) {
|
|
47397
|
+
return { boosted: 0, penalized: 0, flaggedForPruning: 0, ranAt };
|
|
47398
|
+
}
|
|
47399
|
+
const now2 = ranAt.replace("T", " ").slice(0, 19);
|
|
47400
|
+
let boosted = 0;
|
|
47401
|
+
let penalized = 0;
|
|
47402
|
+
let usageRows = [];
|
|
47403
|
+
try {
|
|
47404
|
+
usageRows = typedAll(
|
|
47405
|
+
nativeDb.prepare(
|
|
47406
|
+
`SELECT entry_id, outcome, SUM(used) AS used_count
|
|
47407
|
+
FROM brain_usage_log
|
|
47408
|
+
WHERE outcome IN ('success', 'failure')
|
|
47409
|
+
GROUP BY entry_id, outcome`
|
|
47410
|
+
)
|
|
47411
|
+
);
|
|
47412
|
+
} catch {
|
|
47413
|
+
usageRows = [];
|
|
47414
|
+
}
|
|
47415
|
+
for (const row of usageRows) {
|
|
47416
|
+
const table = tableForId(row.entry_id);
|
|
47417
|
+
if (!table) continue;
|
|
47418
|
+
if (row.outcome === "success" && row.used_count > 0) {
|
|
47419
|
+
applyQualityDelta(nativeDb, table, row.entry_id, 0.05, now2);
|
|
47420
|
+
boosted++;
|
|
47421
|
+
} else if (row.outcome === "failure" && row.used_count > 0) {
|
|
47422
|
+
applyQualityDelta(nativeDb, table, row.entry_id, -0.05, now2);
|
|
47423
|
+
penalized++;
|
|
47424
|
+
}
|
|
47425
|
+
}
|
|
47426
|
+
const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString().replace("T", " ").slice(0, 19);
|
|
47427
|
+
let flaggedForPruning = 0;
|
|
47428
|
+
const pruneTargetTables = [
|
|
47429
|
+
{ table: "brain_decisions", dateCol: "created_at" },
|
|
47430
|
+
{ table: "brain_patterns", dateCol: "extracted_at" },
|
|
47431
|
+
{ table: "brain_learnings", dateCol: "created_at" },
|
|
47432
|
+
{ table: "brain_observations", dateCol: "created_at" }
|
|
47433
|
+
];
|
|
47434
|
+
for (const { table, dateCol } of pruneTargetTables) {
|
|
47435
|
+
try {
|
|
47436
|
+
const result = nativeDb.prepare(
|
|
47437
|
+
`UPDATE ${table}
|
|
47438
|
+
SET prune_candidate = 1
|
|
47439
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
47440
|
+
AND ${dateCol} < ?`
|
|
47441
|
+
).run(cutoffDate);
|
|
47442
|
+
flaggedForPruning += result.changes ?? 0;
|
|
47443
|
+
} catch {
|
|
47444
|
+
}
|
|
47445
|
+
}
|
|
47446
|
+
return { boosted, penalized, flaggedForPruning, ranAt };
|
|
47447
|
+
}
|
|
47448
|
+
async function getMemoryQualityReport(projectRoot) {
|
|
47449
|
+
await ensureUsageLogTable(projectRoot);
|
|
47450
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
47451
|
+
await getBrainDb2(projectRoot);
|
|
47452
|
+
const nativeDb = getBrainNativeDb2();
|
|
47453
|
+
const emptyReport = {
|
|
47454
|
+
totalRetrievals: 0,
|
|
47455
|
+
uniqueEntriesRetrieved: 0,
|
|
47456
|
+
usageRate: 0,
|
|
47457
|
+
topRetrieved: [],
|
|
47458
|
+
neverRetrieved: [],
|
|
47459
|
+
qualityDistribution: { low: 0, medium: 0, high: 0 },
|
|
47460
|
+
tierDistribution: { short: 0, medium: 0, long: 0, unknown: 0 },
|
|
47461
|
+
noiseRatio: 0
|
|
47462
|
+
};
|
|
47463
|
+
if (!nativeDb) return emptyReport;
|
|
47464
|
+
let totalRetrievals = 0;
|
|
47465
|
+
let uniqueEntriesRetrieved = 0;
|
|
47466
|
+
try {
|
|
47467
|
+
const logCount = typedAll(
|
|
47468
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_retrieval_log")
|
|
47469
|
+
);
|
|
47470
|
+
totalRetrievals = logCount[0]?.cnt ?? 0;
|
|
47471
|
+
const uniqueCount = typedAll(
|
|
47472
|
+
nativeDb.prepare(
|
|
47473
|
+
`SELECT COUNT(DISTINCT value) AS cnt
|
|
47474
|
+
FROM brain_retrieval_log,
|
|
47475
|
+
json_each('["' || replace(entry_ids, ',', '","') || '"]')`
|
|
47476
|
+
)
|
|
47477
|
+
);
|
|
47478
|
+
uniqueEntriesRetrieved = uniqueCount[0]?.cnt ?? 0;
|
|
47479
|
+
} catch {
|
|
47480
|
+
}
|
|
47481
|
+
let usageRate = 0;
|
|
47482
|
+
try {
|
|
47483
|
+
const totalUsage = typedAll(
|
|
47484
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_usage_log")
|
|
47485
|
+
);
|
|
47486
|
+
const usedCount = typedAll(
|
|
47487
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_usage_log WHERE used = 1")
|
|
47488
|
+
);
|
|
47489
|
+
const total = totalUsage[0]?.cnt ?? 0;
|
|
47490
|
+
const used = usedCount[0]?.cnt ?? 0;
|
|
47491
|
+
usageRate = total > 0 ? used / total : 0;
|
|
47492
|
+
} catch {
|
|
47493
|
+
}
|
|
47494
|
+
const topRetrieved = [];
|
|
47495
|
+
try {
|
|
47496
|
+
const rows = typedAll(
|
|
47497
|
+
nativeDb.prepare(
|
|
47498
|
+
`SELECT id,
|
|
47499
|
+
'decision' AS type,
|
|
47500
|
+
decision AS title,
|
|
47501
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
47502
|
+
FROM brain_decisions
|
|
47503
|
+
UNION ALL
|
|
47504
|
+
SELECT id,
|
|
47505
|
+
'pattern' AS type,
|
|
47506
|
+
pattern AS title,
|
|
47507
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
47508
|
+
FROM brain_patterns
|
|
47509
|
+
UNION ALL
|
|
47510
|
+
SELECT id,
|
|
47511
|
+
'learning' AS type,
|
|
47512
|
+
insight AS title,
|
|
47513
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
47514
|
+
FROM brain_learnings
|
|
47515
|
+
UNION ALL
|
|
47516
|
+
SELECT id,
|
|
47517
|
+
'observation' AS type,
|
|
47518
|
+
title AS title,
|
|
47519
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
47520
|
+
FROM brain_observations
|
|
47521
|
+
ORDER BY citation_count DESC
|
|
47522
|
+
LIMIT 10`
|
|
47523
|
+
)
|
|
47524
|
+
);
|
|
47525
|
+
for (const r of rows) {
|
|
47526
|
+
topRetrieved.push({
|
|
47527
|
+
id: r.id,
|
|
47528
|
+
type: r.type,
|
|
47529
|
+
title: String(r.title ?? "").slice(0, 120),
|
|
47530
|
+
citationCount: r.citation_count
|
|
47531
|
+
});
|
|
47532
|
+
}
|
|
47533
|
+
} catch {
|
|
47534
|
+
}
|
|
47535
|
+
const neverRetrieved = [];
|
|
47536
|
+
try {
|
|
47537
|
+
const rows = typedAll(
|
|
47538
|
+
nativeDb.prepare(
|
|
47539
|
+
`SELECT id,
|
|
47540
|
+
'decision' AS type,
|
|
47541
|
+
decision AS title,
|
|
47542
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
47543
|
+
FROM brain_decisions
|
|
47544
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
47545
|
+
UNION ALL
|
|
47546
|
+
SELECT id,
|
|
47547
|
+
'pattern' AS type,
|
|
47548
|
+
pattern AS title,
|
|
47549
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
47550
|
+
FROM brain_patterns
|
|
47551
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
47552
|
+
UNION ALL
|
|
47553
|
+
SELECT id,
|
|
47554
|
+
'learning' AS type,
|
|
47555
|
+
insight AS title,
|
|
47556
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
47557
|
+
FROM brain_learnings
|
|
47558
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
47559
|
+
UNION ALL
|
|
47560
|
+
SELECT id,
|
|
47561
|
+
'observation' AS type,
|
|
47562
|
+
title AS title,
|
|
47563
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
47564
|
+
FROM brain_observations
|
|
47565
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
47566
|
+
ORDER BY quality_score ASC
|
|
47567
|
+
LIMIT 10`
|
|
47568
|
+
)
|
|
47569
|
+
);
|
|
47570
|
+
for (const r of rows) {
|
|
47571
|
+
neverRetrieved.push({
|
|
47572
|
+
id: r.id,
|
|
47573
|
+
type: r.type,
|
|
47574
|
+
title: String(r.title ?? "").slice(0, 120),
|
|
47575
|
+
qualityScore: r.quality_score
|
|
47576
|
+
});
|
|
47577
|
+
}
|
|
47578
|
+
} catch {
|
|
47579
|
+
}
|
|
47580
|
+
let qualityDistribution = { low: 0, medium: 0, high: 0 };
|
|
47581
|
+
try {
|
|
47582
|
+
const rows = typedAll(
|
|
47583
|
+
nativeDb.prepare(
|
|
47584
|
+
`SELECT
|
|
47585
|
+
SUM(CASE WHEN qs < 0.3 THEN 1 ELSE 0 END) AS low,
|
|
47586
|
+
SUM(CASE WHEN qs >= 0.3 AND qs <= 0.6 THEN 1 ELSE 0 END) AS medium,
|
|
47587
|
+
SUM(CASE WHEN qs > 0.6 THEN 1 ELSE 0 END) AS high
|
|
47588
|
+
FROM (
|
|
47589
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_decisions
|
|
47590
|
+
UNION ALL
|
|
47591
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_patterns
|
|
47592
|
+
UNION ALL
|
|
47593
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_learnings
|
|
47594
|
+
UNION ALL
|
|
47595
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_observations
|
|
47596
|
+
)`
|
|
47597
|
+
)
|
|
47598
|
+
);
|
|
47599
|
+
if (rows[0]) {
|
|
47600
|
+
qualityDistribution = {
|
|
47601
|
+
low: rows[0].low ?? 0,
|
|
47602
|
+
medium: rows[0].medium ?? 0,
|
|
47603
|
+
high: rows[0].high ?? 0
|
|
47604
|
+
};
|
|
47605
|
+
}
|
|
47606
|
+
} catch {
|
|
47607
|
+
}
|
|
47608
|
+
const tierDistribution = { short: 0, medium: 0, long: 0, unknown: 0 };
|
|
47609
|
+
try {
|
|
47610
|
+
const rows = typedAll(
|
|
47611
|
+
nativeDb.prepare(
|
|
47612
|
+
`SELECT memory_tier AS tier, COUNT(*) AS cnt
|
|
47613
|
+
FROM (
|
|
47614
|
+
SELECT memory_tier FROM brain_decisions
|
|
47615
|
+
UNION ALL
|
|
47616
|
+
SELECT memory_tier FROM brain_patterns
|
|
47617
|
+
UNION ALL
|
|
47618
|
+
SELECT memory_tier FROM brain_learnings
|
|
47619
|
+
UNION ALL
|
|
47620
|
+
SELECT memory_tier FROM brain_observations
|
|
47621
|
+
)
|
|
47622
|
+
GROUP BY memory_tier`
|
|
47623
|
+
)
|
|
47624
|
+
);
|
|
47625
|
+
for (const r of rows) {
|
|
47626
|
+
const tier = r.tier?.toLowerCase() ?? "unknown";
|
|
47627
|
+
if (tier === "short" || tier === "medium" || tier === "long") {
|
|
47628
|
+
tierDistribution[tier] += r.cnt;
|
|
47629
|
+
} else {
|
|
47630
|
+
tierDistribution.unknown += r.cnt;
|
|
47631
|
+
}
|
|
47632
|
+
}
|
|
47633
|
+
} catch {
|
|
47634
|
+
}
|
|
47635
|
+
const totalEntries = qualityDistribution.low + qualityDistribution.medium + qualityDistribution.high;
|
|
47636
|
+
const noiseRatio = totalEntries > 0 ? qualityDistribution.low / totalEntries : 0;
|
|
47637
|
+
return {
|
|
47638
|
+
totalRetrievals,
|
|
47639
|
+
uniqueEntriesRetrieved,
|
|
47640
|
+
usageRate,
|
|
47641
|
+
topRetrieved,
|
|
47642
|
+
neverRetrieved,
|
|
47643
|
+
qualityDistribution,
|
|
47644
|
+
tierDistribution,
|
|
47645
|
+
noiseRatio
|
|
47646
|
+
};
|
|
47647
|
+
}
|
|
47648
|
+
var init_quality_feedback = __esm({
|
|
47649
|
+
"packages/core/src/memory/quality-feedback.ts"() {
|
|
47650
|
+
"use strict";
|
|
47651
|
+
init_typed_query();
|
|
47652
|
+
}
|
|
47653
|
+
});
|
|
47654
|
+
|
|
46667
47655
|
// packages/core/src/hooks/handlers/task-hooks.ts
|
|
46668
47656
|
async function handleToolStart(projectRoot, payload) {
|
|
46669
47657
|
const { observeBrain: observeBrain2 } = await Promise.resolve().then(() => (init_brain_retrieval(), brain_retrieval_exports));
|
|
@@ -46697,6 +47685,13 @@ async function handleToolComplete(projectRoot, payload) {
|
|
|
46697
47685
|
} catch {
|
|
46698
47686
|
}
|
|
46699
47687
|
});
|
|
47688
|
+
setImmediate(async () => {
|
|
47689
|
+
try {
|
|
47690
|
+
const { correlateOutcomes: correlateOutcomes2 } = await Promise.resolve().then(() => (init_quality_feedback(), quality_feedback_exports));
|
|
47691
|
+
await correlateOutcomes2(projectRoot);
|
|
47692
|
+
} catch {
|
|
47693
|
+
}
|
|
47694
|
+
});
|
|
46700
47695
|
await maybeRefreshMemoryBridge(projectRoot);
|
|
46701
47696
|
}
|
|
46702
47697
|
var init_task_hooks = __esm({
|
|
@@ -53194,7 +54189,7 @@ function generateRecommendation2(changeType, affectedCount, cascadeDepth, taskId
|
|
|
53194
54189
|
}
|
|
53195
54190
|
}
|
|
53196
54191
|
function scoreTaskMatch(change, task) {
|
|
53197
|
-
const
|
|
54192
|
+
const STOP_WORDS5 = /* @__PURE__ */ new Set([
|
|
53198
54193
|
"a",
|
|
53199
54194
|
"an",
|
|
53200
54195
|
"the",
|
|
@@ -53216,7 +54211,7 @@ function scoreTaskMatch(change, task) {
|
|
|
53216
54211
|
"do",
|
|
53217
54212
|
"not"
|
|
53218
54213
|
]);
|
|
53219
|
-
const tokenise = (text3) => text3.toLowerCase().split(/\W+/).filter((t) => t.length > 2 && !
|
|
54214
|
+
const tokenise = (text3) => text3.toLowerCase().split(/\W+/).filter((t) => t.length > 2 && !STOP_WORDS5.has(t));
|
|
53220
54215
|
const changeTokens = new Set(tokenise(change));
|
|
53221
54216
|
if (changeTokens.size === 0) return 0;
|
|
53222
54217
|
const taskText = `${task.title ?? ""} ${task.description ?? ""}`;
|
|
@@ -59666,6 +60661,7 @@ __export(memory_exports, {
|
|
|
59666
60661
|
bulkLink: () => bulkLink,
|
|
59667
60662
|
compactManifest: () => compactManifest,
|
|
59668
60663
|
consolidateMemories: () => consolidateMemories,
|
|
60664
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
59669
60665
|
detectContradictions: () => detectContradictions,
|
|
59670
60666
|
ensureFts5Tables: () => ensureFts5Tables,
|
|
59671
60667
|
fetchBrainEntries: () => fetchBrainEntries,
|
|
@@ -59676,6 +60672,7 @@ __export(memory_exports, {
|
|
|
59676
60672
|
getLinkedLearnings: () => getLinkedLearnings,
|
|
59677
60673
|
getLinkedPatterns: () => getLinkedPatterns,
|
|
59678
60674
|
getMemoryLinks: () => getMemoryLinks,
|
|
60675
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
59679
60676
|
getTaskLinks: () => getTaskLinks,
|
|
59680
60677
|
hybridSearch: () => hybridSearch,
|
|
59681
60678
|
learningStats: () => learningStats,
|
|
@@ -59717,6 +60714,7 @@ __export(memory_exports, {
|
|
|
59717
60714
|
storePattern: () => storePattern,
|
|
59718
60715
|
storeVerifiedCandidate: () => storeVerifiedCandidate,
|
|
59719
60716
|
timelineBrain: () => timelineBrain,
|
|
60717
|
+
trackMemoryUsage: () => trackMemoryUsage,
|
|
59720
60718
|
unlinkMemoryFromTask: () => unlinkMemoryFromTask,
|
|
59721
60719
|
updateDecisionOutcome: () => updateDecisionOutcome,
|
|
59722
60720
|
updateResearch: () => updateResearch,
|
|
@@ -60339,6 +61337,7 @@ var init_memory = __esm({
|
|
|
60339
61337
|
init_extraction_gate();
|
|
60340
61338
|
init_learnings();
|
|
60341
61339
|
init_patterns();
|
|
61340
|
+
init_quality_feedback();
|
|
60342
61341
|
}
|
|
60343
61342
|
});
|
|
60344
61343
|
|
|
@@ -64053,8 +65052,8 @@ var init_deps = __esm({
|
|
|
64053
65052
|
});
|
|
64054
65053
|
|
|
64055
65054
|
// packages/core/src/nexus/discover.ts
|
|
64056
|
-
function
|
|
64057
|
-
return text3.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w2) => w2.length > 2 && !
|
|
65055
|
+
function extractKeywords4(text3) {
|
|
65056
|
+
return text3.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w2) => w2.length > 2 && !STOP_WORDS4.has(w2));
|
|
64058
65057
|
}
|
|
64059
65058
|
async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
64060
65059
|
if (!validateSyntax(taskQuery)) {
|
|
@@ -64077,7 +65076,7 @@ async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
|
64077
65076
|
const sourceLabels = new Set(sourceTask.labels ?? []);
|
|
64078
65077
|
const sourceDesc = (sourceTask.description ?? "").toLowerCase();
|
|
64079
65078
|
const sourceTitle = (sourceTask.title ?? "").toLowerCase();
|
|
64080
|
-
const sourceWords =
|
|
65079
|
+
const sourceWords = extractKeywords4(sourceTitle + " " + sourceDesc);
|
|
64081
65080
|
const parsed = parseQuery(taskQuery);
|
|
64082
65081
|
const registry2 = await readRegistry();
|
|
64083
65082
|
if (!registry2) {
|
|
@@ -64112,7 +65111,7 @@ async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
|
64112
65111
|
}
|
|
64113
65112
|
if (method === "description" || method === "auto") {
|
|
64114
65113
|
const taskDesc = ((task.description ?? "") + " " + (task.title ?? "")).toLowerCase();
|
|
64115
|
-
const taskWords =
|
|
65114
|
+
const taskWords = extractKeywords4(taskDesc);
|
|
64116
65115
|
const commonWords = sourceWords.filter((w2) => taskWords.includes(w2));
|
|
64117
65116
|
if (commonWords.length > 0) {
|
|
64118
65117
|
const descScore = commonWords.length / Math.max(sourceWords.length, taskWords.length, 1);
|
|
@@ -64211,14 +65210,14 @@ async function searchAcrossProjects(pattern, projectFilter, limit = 20) {
|
|
|
64211
65210
|
const sliced = results.slice(0, limit);
|
|
64212
65211
|
return { pattern, results: sliced, resultCount: sliced.length };
|
|
64213
65212
|
}
|
|
64214
|
-
var
|
|
65213
|
+
var STOP_WORDS4;
|
|
64215
65214
|
var init_discover = __esm({
|
|
64216
65215
|
"packages/core/src/nexus/discover.ts"() {
|
|
64217
65216
|
"use strict";
|
|
64218
65217
|
init_data_accessor();
|
|
64219
65218
|
init_query4();
|
|
64220
65219
|
init_registry3();
|
|
64221
|
-
|
|
65220
|
+
STOP_WORDS4 = /* @__PURE__ */ new Set([
|
|
64222
65221
|
"the",
|
|
64223
65222
|
"a",
|
|
64224
65223
|
"an",
|
|
@@ -65201,6 +66200,19 @@ async function completeTask(options, cwd, accessor) {
|
|
|
65201
66200
|
})()
|
|
65202
66201
|
).catch(() => {
|
|
65203
66202
|
});
|
|
66203
|
+
try {
|
|
66204
|
+
const { hooks: hooks2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
66205
|
+
await hooks2.dispatch("PostToolUse", cwd ?? process.cwd(), {
|
|
66206
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
66207
|
+
taskId: options.taskId,
|
|
66208
|
+
taskTitle: task.title,
|
|
66209
|
+
previousStatus: before.status,
|
|
66210
|
+
newStatus: "done",
|
|
66211
|
+
unblockedCount: unblockedTasks.length
|
|
66212
|
+
}).catch(() => {
|
|
66213
|
+
});
|
|
66214
|
+
} catch {
|
|
66215
|
+
}
|
|
65204
66216
|
return {
|
|
65205
66217
|
task,
|
|
65206
66218
|
...autoCompleted.length > 0 && { autoCompleted },
|
|
@@ -66038,7 +67050,7 @@ __export(nexus_exports, {
|
|
|
66038
67050
|
criticalPath: () => criticalPath,
|
|
66039
67051
|
discoverRelated: () => discoverRelated,
|
|
66040
67052
|
executeTransfer: () => executeTransfer,
|
|
66041
|
-
extractKeywords: () =>
|
|
67053
|
+
extractKeywords: () => extractKeywords4,
|
|
66042
67054
|
generateProjectHash: () => generateProjectHash,
|
|
66043
67055
|
getCurrentProject: () => getCurrentProject,
|
|
66044
67056
|
getNexusCacheDir: () => getNexusCacheDir,
|
|
@@ -70464,6 +71476,7 @@ __export(research_exports, {
|
|
|
70464
71476
|
bulkLink: () => bulkLink,
|
|
70465
71477
|
compactManifest: () => compactManifest,
|
|
70466
71478
|
consolidateMemories: () => consolidateMemories,
|
|
71479
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
70467
71480
|
detectContradictions: () => detectContradictions,
|
|
70468
71481
|
ensureFts5Tables: () => ensureFts5Tables,
|
|
70469
71482
|
fetchBrainEntries: () => fetchBrainEntries,
|
|
@@ -70474,6 +71487,7 @@ __export(research_exports, {
|
|
|
70474
71487
|
getLinkedLearnings: () => getLinkedLearnings,
|
|
70475
71488
|
getLinkedPatterns: () => getLinkedPatterns,
|
|
70476
71489
|
getMemoryLinks: () => getMemoryLinks,
|
|
71490
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
70477
71491
|
getTaskLinks: () => getTaskLinks,
|
|
70478
71492
|
hybridSearch: () => hybridSearch,
|
|
70479
71493
|
learningStats: () => learningStats,
|
|
@@ -70515,6 +71529,7 @@ __export(research_exports, {
|
|
|
70515
71529
|
storePattern: () => storePattern,
|
|
70516
71530
|
storeVerifiedCandidate: () => storeVerifiedCandidate,
|
|
70517
71531
|
timelineBrain: () => timelineBrain,
|
|
71532
|
+
trackMemoryUsage: () => trackMemoryUsage,
|
|
70518
71533
|
unlinkMemoryFromTask: () => unlinkMemoryFromTask,
|
|
70519
71534
|
updateDecisionOutcome: () => updateDecisionOutcome,
|
|
70520
71535
|
updateResearch: () => updateResearch,
|
|
@@ -90884,6 +91899,22 @@ async function memoryGraphRemove(params, projectRoot) {
|
|
|
90884
91899
|
};
|
|
90885
91900
|
}
|
|
90886
91901
|
}
|
|
91902
|
+
async function memoryQualityReport(projectRoot) {
|
|
91903
|
+
try {
|
|
91904
|
+
const root = resolveRoot(projectRoot);
|
|
91905
|
+
const { getMemoryQualityReport: getMemoryQualityReport2 } = await Promise.resolve().then(() => (init_quality_feedback(), quality_feedback_exports));
|
|
91906
|
+
const report = await getMemoryQualityReport2(root);
|
|
91907
|
+
return { success: true, data: report };
|
|
91908
|
+
} catch (error48) {
|
|
91909
|
+
return {
|
|
91910
|
+
success: false,
|
|
91911
|
+
error: {
|
|
91912
|
+
code: "E_QUALITY_REPORT",
|
|
91913
|
+
message: error48 instanceof Error ? error48.message : String(error48)
|
|
91914
|
+
}
|
|
91915
|
+
};
|
|
91916
|
+
}
|
|
91917
|
+
}
|
|
90887
91918
|
var init_engine_compat = __esm({
|
|
90888
91919
|
"packages/core/src/memory/engine-compat.ts"() {
|
|
90889
91920
|
"use strict";
|
|
@@ -109522,12 +110553,12 @@ import { join as join119 } from "node:path";
|
|
|
109522
110553
|
function typedAll4(db, sql14, ...params) {
|
|
109523
110554
|
return db.prepare(sql14).all(...params);
|
|
109524
110555
|
}
|
|
109525
|
-
function
|
|
110556
|
+
function typedGet2(db, sql14, ...params) {
|
|
109526
110557
|
return db.prepare(sql14).get(...params);
|
|
109527
110558
|
}
|
|
109528
110559
|
function queryIndexMeta(db, projectId) {
|
|
109529
110560
|
try {
|
|
109530
|
-
const nodeMeta =
|
|
110561
|
+
const nodeMeta = typedGet2(
|
|
109531
110562
|
db,
|
|
109532
110563
|
`SELECT COUNT(*) as total_nodes,
|
|
109533
110564
|
COUNT(CASE WHEN kind = 'file' THEN 1 END) as file_count,
|
|
@@ -109536,7 +110567,7 @@ function queryIndexMeta(db, projectId) {
|
|
|
109536
110567
|
WHERE project_id = ?`,
|
|
109537
110568
|
projectId
|
|
109538
110569
|
);
|
|
109539
|
-
const relMeta =
|
|
110570
|
+
const relMeta = typedGet2(
|
|
109540
110571
|
db,
|
|
109541
110572
|
`SELECT COUNT(*) as total_relations
|
|
109542
110573
|
FROM nexus_relations
|
|
@@ -109631,7 +110662,7 @@ function queryCommunities(db, projectId, limit = 6) {
|
|
|
109631
110662
|
}
|
|
109632
110663
|
function queryProcessCount(db, projectId) {
|
|
109633
110664
|
try {
|
|
109634
|
-
const row =
|
|
110665
|
+
const row = typedGet2(
|
|
109635
110666
|
db,
|
|
109636
110667
|
`SELECT COUNT(*) as count
|
|
109637
110668
|
FROM nexus_nodes
|
|
@@ -111232,6 +112263,7 @@ __export(internal_exports, {
|
|
|
111232
112263
|
coreValidateProtocol: () => coreValidateProtocol,
|
|
111233
112264
|
coreValidateSchema: () => coreValidateSchema,
|
|
111234
112265
|
coreValidateTask: () => coreValidateTask,
|
|
112266
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
111235
112267
|
createBackup: () => createBackup,
|
|
111236
112268
|
createConduit: () => createConduit,
|
|
111237
112269
|
createDataAccessor: () => createDataAccessor,
|
|
@@ -111384,6 +112416,7 @@ __export(internal_exports, {
|
|
|
111384
112416
|
getLinksByTaskId: () => getLinksByTaskId,
|
|
111385
112417
|
getLogDir: () => getLogDir,
|
|
111386
112418
|
getLogger: () => getLogger,
|
|
112419
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
111387
112420
|
getMigrationStatus: () => getMigrationStatus2,
|
|
111388
112421
|
getNativeDb: () => getNativeDb,
|
|
111389
112422
|
getNativeOperations: () => getNativeOperations,
|
|
@@ -111554,6 +112587,7 @@ __export(internal_exports, {
|
|
|
111554
112587
|
memoryPatternFind: () => memoryPatternFind,
|
|
111555
112588
|
memoryPatternStats: () => memoryPatternStats,
|
|
111556
112589
|
memoryPatternStore: () => memoryPatternStore,
|
|
112590
|
+
memoryQualityReport: () => memoryQualityReport,
|
|
111557
112591
|
memoryReasonSimilar: () => memoryReasonSimilar,
|
|
111558
112592
|
memoryReasonWhy: () => memoryReasonWhy,
|
|
111559
112593
|
memorySearchHybrid: () => memorySearchHybrid,
|
|
@@ -111766,6 +112800,7 @@ __export(internal_exports, {
|
|
|
111766
112800
|
tokenUsageMethodSchema: () => tokenUsageMethodSchema,
|
|
111767
112801
|
tokenUsageTransportSchema: () => tokenUsageTransportSchema,
|
|
111768
112802
|
touchLink: () => touchLink,
|
|
112803
|
+
trackMemoryUsage: () => trackMemoryUsage,
|
|
111769
112804
|
ui: () => ui_exports,
|
|
111770
112805
|
uncancelTask: () => uncancelTask,
|
|
111771
112806
|
unpackBundle: () => unpackBundle,
|
|
@@ -111853,6 +112888,7 @@ var init_internal = __esm({
|
|
|
111853
112888
|
init_claude_mem_migration();
|
|
111854
112889
|
init_engine_compat();
|
|
111855
112890
|
init_pipeline_manifest_sqlite();
|
|
112891
|
+
init_quality_feedback();
|
|
111856
112892
|
init_token_service();
|
|
111857
112893
|
init_deps();
|
|
111858
112894
|
init_discover();
|
|
@@ -115018,6 +116054,66 @@ var init_registry5 = __esm({
|
|
|
115018
116054
|
sessionRequired: false,
|
|
115019
116055
|
requiredParams: []
|
|
115020
116056
|
},
|
|
116057
|
+
{
|
|
116058
|
+
gateway: "query",
|
|
116059
|
+
domain: "memory",
|
|
116060
|
+
operation: "quality",
|
|
116061
|
+
description: "Memory quality report: retrieval stats, noise ratio, tier distribution",
|
|
116062
|
+
tier: 1,
|
|
116063
|
+
idempotent: true,
|
|
116064
|
+
sessionRequired: false,
|
|
116065
|
+
requiredParams: []
|
|
116066
|
+
},
|
|
116067
|
+
{
|
|
116068
|
+
gateway: "query",
|
|
116069
|
+
domain: "memory",
|
|
116070
|
+
operation: "code.links",
|
|
116071
|
+
description: "List code_reference edges connecting memories to nexus code symbols",
|
|
116072
|
+
tier: 1,
|
|
116073
|
+
idempotent: true,
|
|
116074
|
+
sessionRequired: false,
|
|
116075
|
+
requiredParams: []
|
|
116076
|
+
},
|
|
116077
|
+
{
|
|
116078
|
+
gateway: "query",
|
|
116079
|
+
domain: "memory",
|
|
116080
|
+
operation: "code.memories-for-code",
|
|
116081
|
+
description: "Find memories linked to a code symbol via code_reference edges",
|
|
116082
|
+
tier: 1,
|
|
116083
|
+
idempotent: true,
|
|
116084
|
+
sessionRequired: false,
|
|
116085
|
+
requiredParams: ["symbol"]
|
|
116086
|
+
},
|
|
116087
|
+
{
|
|
116088
|
+
gateway: "query",
|
|
116089
|
+
domain: "memory",
|
|
116090
|
+
operation: "code.for-memory",
|
|
116091
|
+
description: "Find code symbols linked to a memory entry via code_reference edges",
|
|
116092
|
+
tier: 1,
|
|
116093
|
+
idempotent: true,
|
|
116094
|
+
sessionRequired: false,
|
|
116095
|
+
requiredParams: ["memoryId"]
|
|
116096
|
+
},
|
|
116097
|
+
{
|
|
116098
|
+
gateway: "mutate",
|
|
116099
|
+
domain: "memory",
|
|
116100
|
+
operation: "code.link",
|
|
116101
|
+
description: "Create code_reference edge from memory to nexus symbol",
|
|
116102
|
+
tier: 1,
|
|
116103
|
+
idempotent: false,
|
|
116104
|
+
sessionRequired: false,
|
|
116105
|
+
requiredParams: ["memoryId", "codeSymbol"]
|
|
116106
|
+
},
|
|
116107
|
+
{
|
|
116108
|
+
gateway: "mutate",
|
|
116109
|
+
domain: "memory",
|
|
116110
|
+
operation: "code.auto-link",
|
|
116111
|
+
description: "Scan memories for entity references and auto-link to nexus nodes",
|
|
116112
|
+
tier: 1,
|
|
116113
|
+
idempotent: true,
|
|
116114
|
+
sessionRequired: false,
|
|
116115
|
+
requiredParams: []
|
|
116116
|
+
},
|
|
115021
116117
|
{
|
|
115022
116118
|
gateway: "mutate",
|
|
115023
116119
|
domain: "pipeline",
|
|
@@ -118039,7 +119135,31 @@ async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectR
|
|
|
118039
119135
|
}
|
|
118040
119136
|
} catch {
|
|
118041
119137
|
}
|
|
119138
|
+
try {
|
|
119139
|
+
const { hooks: hooks2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
119140
|
+
await hooks2.dispatch("SubagentStart", cwd, {
|
|
119141
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
119142
|
+
taskId,
|
|
119143
|
+
agentId: cleoSpawnContext.options?.preferredAgent ?? `worker-${taskId}`,
|
|
119144
|
+
role: protocolType || "worker",
|
|
119145
|
+
providerId: adapter.providerId
|
|
119146
|
+
}).catch(() => {
|
|
119147
|
+
});
|
|
119148
|
+
} catch {
|
|
119149
|
+
}
|
|
118042
119150
|
const result = await adapter.spawn(cleoSpawnContext);
|
|
119151
|
+
try {
|
|
119152
|
+
const { hooks: hooks2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
119153
|
+
await hooks2.dispatch("SubagentStop", cwd, {
|
|
119154
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
119155
|
+
taskId,
|
|
119156
|
+
agentId: cleoSpawnContext.options?.preferredAgent ?? `worker-${taskId}`,
|
|
119157
|
+
status: result.status,
|
|
119158
|
+
instanceId: result.instanceId
|
|
119159
|
+
}).catch(() => {
|
|
119160
|
+
});
|
|
119161
|
+
} catch {
|
|
119162
|
+
}
|
|
118043
119163
|
void sendConduitEvent(cwd, "cleo-core", {
|
|
118044
119164
|
event: "agent.spawned",
|
|
118045
119165
|
taskId,
|
|
@@ -123521,6 +124641,33 @@ var init_memory2 = __esm({
|
|
|
123521
124641
|
);
|
|
123522
124642
|
return wrapResult(result, "query", "memory", operation, startTime);
|
|
123523
124643
|
}
|
|
124644
|
+
case "quality": {
|
|
124645
|
+
const result = await memoryQualityReport(projectRoot);
|
|
124646
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
124647
|
+
}
|
|
124648
|
+
case "code.links": {
|
|
124649
|
+
const { listCodeLinks: listCodeLinks2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
124650
|
+
const result = await listCodeLinks2(projectRoot);
|
|
124651
|
+
return wrapResult(result, "query", "memory", operation, startTime);
|
|
124652
|
+
}
|
|
124653
|
+
case "code.memories-for-code": {
|
|
124654
|
+
const symbol2 = params?.symbol;
|
|
124655
|
+
if (!symbol2) {
|
|
124656
|
+
return errorResult("query", "memory", operation, "E_INVALID_INPUT", "symbol is required", startTime);
|
|
124657
|
+
}
|
|
124658
|
+
const { queryMemoriesForCode: queryMemoriesForCode2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
124659
|
+
const result = await queryMemoriesForCode2(projectRoot, symbol2);
|
|
124660
|
+
return wrapResult({ success: true, data: result }, "query", "memory", operation, startTime);
|
|
124661
|
+
}
|
|
124662
|
+
case "code.for-memory": {
|
|
124663
|
+
const memoryId = params?.memoryId;
|
|
124664
|
+
if (!memoryId) {
|
|
124665
|
+
return errorResult("query", "memory", operation, "E_INVALID_INPUT", "memoryId is required", startTime);
|
|
124666
|
+
}
|
|
124667
|
+
const { queryCodeForMemory: queryCodeForMemory2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
124668
|
+
const result = await queryCodeForMemory2(projectRoot, memoryId);
|
|
124669
|
+
return wrapResult({ success: true, data: result }, "query", "memory", operation, startTime);
|
|
124670
|
+
}
|
|
123524
124671
|
default:
|
|
123525
124672
|
return unsupportedOp("query", "memory", operation, startTime);
|
|
123526
124673
|
}
|
|
@@ -123691,6 +124838,21 @@ var init_memory2 = __esm({
|
|
|
123691
124838
|
);
|
|
123692
124839
|
return wrapResult(result, "mutate", "memory", operation, startTime);
|
|
123693
124840
|
}
|
|
124841
|
+
case "code.link": {
|
|
124842
|
+
const memoryId = params?.memoryId;
|
|
124843
|
+
const codeSymbol = params?.codeSymbol;
|
|
124844
|
+
if (!memoryId || !codeSymbol) {
|
|
124845
|
+
return errorResult("mutate", "memory", operation, "E_INVALID_INPUT", "memoryId and codeSymbol are required", startTime);
|
|
124846
|
+
}
|
|
124847
|
+
const { linkMemoryToCode: linkMemoryToCode2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
124848
|
+
const linked = await linkMemoryToCode2(projectRoot, memoryId, codeSymbol);
|
|
124849
|
+
return wrapResult({ success: true, data: { linked } }, "mutate", "memory", operation, startTime);
|
|
124850
|
+
}
|
|
124851
|
+
case "code.auto-link": {
|
|
124852
|
+
const { autoLinkMemories: autoLinkMemories2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
124853
|
+
const result = await autoLinkMemories2(projectRoot);
|
|
124854
|
+
return wrapResult({ success: true, data: result }, "mutate", "memory", operation, startTime);
|
|
124855
|
+
}
|
|
123694
124856
|
default:
|
|
123695
124857
|
return unsupportedOp("mutate", "memory", operation, startTime);
|
|
123696
124858
|
}
|
|
@@ -123723,7 +124885,11 @@ var init_memory2 = __esm({
|
|
|
123723
124885
|
"graph.stats",
|
|
123724
124886
|
"reason.why",
|
|
123725
124887
|
"reason.similar",
|
|
123726
|
-
"search.hybrid"
|
|
124888
|
+
"search.hybrid",
|
|
124889
|
+
"quality",
|
|
124890
|
+
"code.links",
|
|
124891
|
+
"code.memories-for-code",
|
|
124892
|
+
"code.for-memory"
|
|
123727
124893
|
],
|
|
123728
124894
|
mutate: [
|
|
123729
124895
|
"observe",
|
|
@@ -123732,7 +124898,9 @@ var init_memory2 = __esm({
|
|
|
123732
124898
|
"learning.store",
|
|
123733
124899
|
"link",
|
|
123734
124900
|
"graph.add",
|
|
123735
|
-
"graph.remove"
|
|
124901
|
+
"graph.remove",
|
|
124902
|
+
"code.link",
|
|
124903
|
+
"code.auto-link"
|
|
123736
124904
|
]
|
|
123737
124905
|
};
|
|
123738
124906
|
}
|
|
@@ -133450,6 +134618,66 @@ function registerBrainCommand(program) {
|
|
|
133450
134618
|
process.exit(1);
|
|
133451
134619
|
}
|
|
133452
134620
|
});
|
|
134621
|
+
brain.command("quality").description(
|
|
134622
|
+
"Show memory quality metrics: retrieval rates, top/never-retrieved entries, quality distribution, and noise ratio."
|
|
134623
|
+
).option("--json", "Output results as JSON").action(async (opts) => {
|
|
134624
|
+
const root = getProjectRoot();
|
|
134625
|
+
const isJson = !!opts.json;
|
|
134626
|
+
try {
|
|
134627
|
+
const report = await getMemoryQualityReport(root);
|
|
134628
|
+
if (isJson) {
|
|
134629
|
+
console.log(
|
|
134630
|
+
JSON.stringify(
|
|
134631
|
+
{
|
|
134632
|
+
success: true,
|
|
134633
|
+
data: report,
|
|
134634
|
+
meta: { operation: "brain.quality", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
134635
|
+
},
|
|
134636
|
+
null,
|
|
134637
|
+
2
|
|
134638
|
+
)
|
|
134639
|
+
);
|
|
134640
|
+
return;
|
|
134641
|
+
}
|
|
134642
|
+
console.log("\nBrain Memory Quality Report");
|
|
134643
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
134644
|
+
console.log(` Total retrievals: ${report.totalRetrievals}`);
|
|
134645
|
+
console.log(` Unique entries hit: ${report.uniqueEntriesRetrieved}`);
|
|
134646
|
+
console.log(` Usage rate: ${(report.usageRate * 100).toFixed(1)}%`);
|
|
134647
|
+
console.log(` Noise ratio: ${(report.noiseRatio * 100).toFixed(1)}%`);
|
|
134648
|
+
console.log("\nQuality Distribution");
|
|
134649
|
+
console.log(` Low (<0.3): ${report.qualityDistribution.low}`);
|
|
134650
|
+
console.log(` Med (0.3-0.6): ${report.qualityDistribution.medium}`);
|
|
134651
|
+
console.log(` High (>0.6): ${report.qualityDistribution.high}`);
|
|
134652
|
+
console.log("\nTier Distribution");
|
|
134653
|
+
console.log(` Short: ${report.tierDistribution.short}`);
|
|
134654
|
+
console.log(` Medium: ${report.tierDistribution.medium}`);
|
|
134655
|
+
console.log(` Long: ${report.tierDistribution.long}`);
|
|
134656
|
+
if (report.tierDistribution.unknown > 0) {
|
|
134657
|
+
console.log(` Unknown: ${report.tierDistribution.unknown}`);
|
|
134658
|
+
}
|
|
134659
|
+
if (report.topRetrieved.length > 0) {
|
|
134660
|
+
console.log("\nTop 10 Most Retrieved");
|
|
134661
|
+
for (const e of report.topRetrieved) {
|
|
134662
|
+
console.log(` [${e.citationCount}x] ${e.id} ${e.title.slice(0, 60)}`);
|
|
134663
|
+
}
|
|
134664
|
+
}
|
|
134665
|
+
if (report.neverRetrieved.length > 0) {
|
|
134666
|
+
console.log("\nNever Retrieved (pruning candidates)");
|
|
134667
|
+
for (const e of report.neverRetrieved) {
|
|
134668
|
+
console.log(` q=${e.qualityScore.toFixed(2)} ${e.id} ${e.title.slice(0, 60)}`);
|
|
134669
|
+
}
|
|
134670
|
+
}
|
|
134671
|
+
} catch (err) {
|
|
134672
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
134673
|
+
if (isJson) {
|
|
134674
|
+
console.log(JSON.stringify({ success: false, error: message }));
|
|
134675
|
+
} else {
|
|
134676
|
+
console.error(`Brain quality report failed: ${message}`);
|
|
134677
|
+
}
|
|
134678
|
+
process.exit(1);
|
|
134679
|
+
}
|
|
134680
|
+
});
|
|
133453
134681
|
}
|
|
133454
134682
|
|
|
133455
134683
|
// packages/cleo/src/cli/commands/briefing.ts
|
|
@@ -136519,6 +137747,47 @@ function registerMemoryBrainCommand(program) {
|
|
|
136519
137747
|
{ command: "memory", operation: "memory.search.hybrid" }
|
|
136520
137748
|
);
|
|
136521
137749
|
});
|
|
137750
|
+
memory.command("code-links").description("Show code \u2194 memory connections (code_reference edges between brain and nexus)").option("--limit <n>", "Maximum entries to return (default 100)", parseInt).option("--json", "Output as JSON").action(async (opts) => {
|
|
137751
|
+
await dispatchFromCli(
|
|
137752
|
+
"query",
|
|
137753
|
+
"memory",
|
|
137754
|
+
"code.links",
|
|
137755
|
+
{
|
|
137756
|
+
...opts["limit"] !== void 0 && { limit: opts["limit"] }
|
|
137757
|
+
},
|
|
137758
|
+
{ command: "memory", operation: "memory.code.links" }
|
|
137759
|
+
);
|
|
137760
|
+
});
|
|
137761
|
+
memory.command("code-auto-link").description("Scan brain memory nodes for entity references and auto-link to nexus code nodes").option("--json", "Output as JSON").action(async () => {
|
|
137762
|
+
await dispatchFromCli(
|
|
137763
|
+
"mutate",
|
|
137764
|
+
"memory",
|
|
137765
|
+
"code.auto-link",
|
|
137766
|
+
{},
|
|
137767
|
+
{
|
|
137768
|
+
command: "memory",
|
|
137769
|
+
operation: "memory.code.auto-link"
|
|
137770
|
+
}
|
|
137771
|
+
);
|
|
137772
|
+
});
|
|
137773
|
+
memory.command("code-memories-for-code <symbol>").description("Find brain memory nodes that reference a given nexus code symbol").option("--json", "Output as JSON").action(async (symbol2) => {
|
|
137774
|
+
await dispatchFromCli(
|
|
137775
|
+
"query",
|
|
137776
|
+
"memory",
|
|
137777
|
+
"code.memories-for-code",
|
|
137778
|
+
{ symbol: symbol2 },
|
|
137779
|
+
{ command: "memory", operation: "memory.code.memories-for-code" }
|
|
137780
|
+
);
|
|
137781
|
+
});
|
|
137782
|
+
memory.command("code-for-memory <memoryId>").description("Find nexus code nodes referenced by a given brain memory entry").option("--json", "Output as JSON").action(async (memoryId) => {
|
|
137783
|
+
await dispatchFromCli(
|
|
137784
|
+
"query",
|
|
137785
|
+
"memory",
|
|
137786
|
+
"code.for-memory",
|
|
137787
|
+
{ memoryId },
|
|
137788
|
+
{ command: "memory", operation: "memory.code.for-memory" }
|
|
137789
|
+
);
|
|
137790
|
+
});
|
|
136522
137791
|
}
|
|
136523
137792
|
|
|
136524
137793
|
// packages/cleo/src/cli/commands/migrate-claude-mem.ts
|