@cleocode/core 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/hooks/handlers/task-hooks.d.ts.map +1 -1
- package/dist/hooks/handlers/task-hooks.js +11 -0
- package/dist/hooks/handlers/task-hooks.js.map +1 -1
- package/dist/index.js +1048 -33
- package/dist/index.js.map +4 -4
- package/dist/internal.d.ts +3 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +3 -1
- package/dist/internal.js.map +1 -1
- package/dist/memory/brain-lifecycle.d.ts +2 -0
- package/dist/memory/brain-lifecycle.d.ts.map +1 -1
- package/dist/memory/decisions.d.ts.map +1 -1
- package/dist/memory/decisions.js +18 -0
- package/dist/memory/decisions.js.map +1 -1
- package/dist/memory/engine-compat.d.ts +17 -0
- package/dist/memory/engine-compat.d.ts.map +1 -1
- package/dist/memory/engine-compat.js +36 -0
- package/dist/memory/engine-compat.js.map +1 -1
- package/dist/memory/graph-memory-bridge.d.ts +158 -0
- package/dist/memory/graph-memory-bridge.d.ts.map +1 -0
- package/dist/memory/graph-memory-bridge.js +519 -0
- package/dist/memory/graph-memory-bridge.js.map +1 -0
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +2 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/learnings.d.ts.map +1 -1
- package/dist/memory/learnings.js +18 -0
- package/dist/memory/learnings.js.map +1 -1
- package/dist/memory/llm-extraction.js.map +1 -1
- package/dist/memory/patterns.d.ts.map +1 -1
- package/dist/memory/patterns.js +18 -0
- package/dist/memory/patterns.js.map +1 -1
- package/dist/memory/quality-feedback.d.ts +129 -0
- package/dist/memory/quality-feedback.d.ts.map +1 -0
- package/dist/memory/quality-feedback.js +449 -0
- package/dist/memory/quality-feedback.js.map +1 -0
- package/dist/memory/sleep-consolidation.d.ts +98 -0
- package/dist/memory/sleep-consolidation.d.ts.map +1 -0
- package/dist/memory/sleep-consolidation.js +706 -0
- package/dist/memory/sleep-consolidation.js.map +1 -0
- package/dist/memory/temporal-supersession.d.ts +155 -0
- package/dist/memory/temporal-supersession.d.ts.map +1 -0
- package/dist/memory/temporal-supersession.js +406 -0
- package/dist/memory/temporal-supersession.js.map +1 -0
- package/dist/tasks/complete.d.ts.map +1 -1
- package/package.json +8 -8
- package/src/hooks/handlers/task-hooks.ts +11 -0
- package/src/internal.ts +12 -0
- package/src/memory/__tests__/graph-memory-bridge.test.ts +357 -0
- package/src/memory/__tests__/llm-extraction.test.ts +17 -0
- package/src/memory/__tests__/quality-feedback.test.ts +418 -0
- package/src/memory/__tests__/sleep-consolidation.test.ts +790 -0
- package/src/memory/__tests__/temporal-supersession.test.ts +534 -0
- package/src/memory/brain-lifecycle.ts +13 -0
- package/src/memory/decisions.ts +24 -0
- package/src/memory/engine-compat.ts +37 -0
- package/src/memory/graph-memory-bridge.ts +751 -0
- package/src/memory/index.ts +2 -0
- package/src/memory/learnings.ts +24 -0
- package/src/memory/patterns.ts +24 -0
- package/src/memory/quality-feedback.ts +640 -0
- package/src/memory/sleep-consolidation.ts +932 -0
- package/src/memory/temporal-supersession.ts +568 -0
- package/src/store/__tests__/performance-safety.test.ts +4 -4
- package/src/tasks/complete.ts +20 -0
package/dist/index.js
CHANGED
|
@@ -18648,6 +18648,210 @@ var init_quality_scoring = __esm({
|
|
|
18648
18648
|
}
|
|
18649
18649
|
});
|
|
18650
18650
|
|
|
18651
|
+
// packages/core/src/store/typed-query.ts
|
|
18652
|
+
function typedAll(stmt, ...params) {
|
|
18653
|
+
return stmt.all(...params);
|
|
18654
|
+
}
|
|
18655
|
+
function typedGet(stmt, ...params) {
|
|
18656
|
+
return stmt.get(...params);
|
|
18657
|
+
}
|
|
18658
|
+
var init_typed_query = __esm({
|
|
18659
|
+
"packages/core/src/store/typed-query.ts"() {
|
|
18660
|
+
"use strict";
|
|
18661
|
+
}
|
|
18662
|
+
});
|
|
18663
|
+
|
|
18664
|
+
// packages/core/src/memory/temporal-supersession.ts
|
|
18665
|
+
function extractKeywords(text3) {
|
|
18666
|
+
const words = text3.toLowerCase().replace(/[^a-z0-9\s\-_]/g, " ").split(/\s+/);
|
|
18667
|
+
const keywords = /* @__PURE__ */ new Set();
|
|
18668
|
+
for (const w of words) {
|
|
18669
|
+
if (w.length >= 4 && !STOP_WORDS.has(w)) {
|
|
18670
|
+
keywords.add(w);
|
|
18671
|
+
}
|
|
18672
|
+
}
|
|
18673
|
+
return keywords;
|
|
18674
|
+
}
|
|
18675
|
+
function keywordSimilarity(textA, textB) {
|
|
18676
|
+
const kwA = extractKeywords(textA);
|
|
18677
|
+
const kwB = extractKeywords(textB);
|
|
18678
|
+
if (kwA.size === 0 || kwB.size === 0) return { similarity: 0, shared: [] };
|
|
18679
|
+
const shared = [];
|
|
18680
|
+
for (const w of kwA) {
|
|
18681
|
+
if (kwB.has(w)) shared.push(w);
|
|
18682
|
+
}
|
|
18683
|
+
if (shared.length < MIN_SHARED_KEYWORDS) return { similarity: 0, shared: [] };
|
|
18684
|
+
const union3 = kwA.size + kwB.size - shared.length;
|
|
18685
|
+
const similarity = union3 > 0 ? shared.length / union3 : 0;
|
|
18686
|
+
return { similarity, shared };
|
|
18687
|
+
}
|
|
18688
|
+
function buildNodeId(type, entryId) {
|
|
18689
|
+
return `${type}:${entryId}`;
|
|
18690
|
+
}
|
|
18691
|
+
async function locateEntry(projectRoot, entryId) {
|
|
18692
|
+
await getBrainDb(projectRoot);
|
|
18693
|
+
const nativeDb = getBrainNativeDb();
|
|
18694
|
+
if (!nativeDb) return null;
|
|
18695
|
+
for (const tc of SUPERSEDABLE_TABLES) {
|
|
18696
|
+
const row = typedGet(
|
|
18697
|
+
nativeDb.prepare(`SELECT id FROM ${tc.table} WHERE id = ? LIMIT 1`),
|
|
18698
|
+
entryId
|
|
18699
|
+
);
|
|
18700
|
+
if (row) {
|
|
18701
|
+
return { tableConfig: tc, nodeId: buildNodeId(tc.type, entryId) };
|
|
18702
|
+
}
|
|
18703
|
+
}
|
|
18704
|
+
return null;
|
|
18705
|
+
}
|
|
18706
|
+
async function supersedeMemory(projectRoot, oldId, newId, reason) {
|
|
18707
|
+
if (!oldId?.trim()) throw new Error("oldId is required");
|
|
18708
|
+
if (!newId?.trim()) throw new Error("newId is required");
|
|
18709
|
+
if (!reason?.trim()) throw new Error("reason is required");
|
|
18710
|
+
if (oldId === newId) throw new Error("oldId and newId must be different entries");
|
|
18711
|
+
await getBrainDb(projectRoot);
|
|
18712
|
+
const nativeDb = getBrainNativeDb();
|
|
18713
|
+
if (!nativeDb) throw new Error("brain.db is unavailable");
|
|
18714
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
18715
|
+
const oldLocation = await locateEntry(projectRoot, oldId);
|
|
18716
|
+
if (!oldLocation) throw new Error(`Entry not found: ${oldId}`);
|
|
18717
|
+
const newLocation = await locateEntry(projectRoot, newId);
|
|
18718
|
+
if (!newLocation) throw new Error(`Entry not found: ${newId}`);
|
|
18719
|
+
const { tableConfig: oldTc, nodeId: oldNodeId } = oldLocation;
|
|
18720
|
+
const { nodeId: newNodeId } = newLocation;
|
|
18721
|
+
try {
|
|
18722
|
+
nativeDb.prepare(
|
|
18723
|
+
`UPDATE ${oldTc.table} SET invalid_at = ?, updated_at = ? WHERE id = ? AND invalid_at IS NULL`
|
|
18724
|
+
).run(now, now, oldId);
|
|
18725
|
+
} catch {
|
|
18726
|
+
}
|
|
18727
|
+
const provenanceText = reason.substring(0, 500);
|
|
18728
|
+
try {
|
|
18729
|
+
nativeDb.prepare(
|
|
18730
|
+
`INSERT OR IGNORE INTO brain_page_edges
|
|
18731
|
+
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
18732
|
+
VALUES (?, ?, 'supersedes', 1.0, ?, ?)`
|
|
18733
|
+
).run(newNodeId, oldNodeId, provenanceText, now);
|
|
18734
|
+
} catch (err) {
|
|
18735
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
18736
|
+
throw new Error(`Failed to create supersedes edge: ${message}`);
|
|
18737
|
+
}
|
|
18738
|
+
return {
|
|
18739
|
+
success: true,
|
|
18740
|
+
oldId,
|
|
18741
|
+
newId,
|
|
18742
|
+
edgeType: "supersedes"
|
|
18743
|
+
};
|
|
18744
|
+
}
|
|
18745
|
+
async function detectSupersession(projectRoot, newEntry) {
|
|
18746
|
+
try {
|
|
18747
|
+
await getBrainDb(projectRoot);
|
|
18748
|
+
const nativeDb = getBrainNativeDb();
|
|
18749
|
+
if (!nativeDb) return [];
|
|
18750
|
+
const newLocation = await locateEntry(projectRoot, newEntry.id);
|
|
18751
|
+
if (!newLocation) return [];
|
|
18752
|
+
const { tableConfig } = newLocation;
|
|
18753
|
+
const existing = typedAll(
|
|
18754
|
+
nativeDb.prepare(`
|
|
18755
|
+
SELECT id, COALESCE(${tableConfig.textCol}, '') AS text,
|
|
18756
|
+
created_at, quality_score
|
|
18757
|
+
FROM ${tableConfig.table}
|
|
18758
|
+
WHERE invalid_at IS NULL
|
|
18759
|
+
AND id != ?
|
|
18760
|
+
ORDER BY created_at DESC
|
|
18761
|
+
LIMIT 200
|
|
18762
|
+
`),
|
|
18763
|
+
newEntry.id
|
|
18764
|
+
);
|
|
18765
|
+
if (existing.length === 0) return [];
|
|
18766
|
+
const candidates = [];
|
|
18767
|
+
for (const row of existing) {
|
|
18768
|
+
if (row.created_at >= newEntry.createdAt) continue;
|
|
18769
|
+
const { similarity, shared } = keywordSimilarity(newEntry.text, row.text);
|
|
18770
|
+
if (similarity >= KEYWORD_OVERLAP_THRESHOLD) {
|
|
18771
|
+
candidates.push({
|
|
18772
|
+
existingId: row.id,
|
|
18773
|
+
similarity,
|
|
18774
|
+
table: tableConfig.table,
|
|
18775
|
+
sharedKeywords: shared.slice(0, 10)
|
|
18776
|
+
});
|
|
18777
|
+
}
|
|
18778
|
+
}
|
|
18779
|
+
candidates.sort((a, b) => b.similarity - a.similarity);
|
|
18780
|
+
return candidates;
|
|
18781
|
+
} catch (err) {
|
|
18782
|
+
console.warn("[temporal-supersession] detectSupersession failed:", err);
|
|
18783
|
+
return [];
|
|
18784
|
+
}
|
|
18785
|
+
}
|
|
18786
|
+
var KEYWORD_OVERLAP_THRESHOLD, MIN_SHARED_KEYWORDS, STOP_WORDS, SUPERSEDABLE_TABLES;
|
|
18787
|
+
var init_temporal_supersession = __esm({
|
|
18788
|
+
"packages/core/src/memory/temporal-supersession.ts"() {
|
|
18789
|
+
"use strict";
|
|
18790
|
+
init_brain_sqlite();
|
|
18791
|
+
init_typed_query();
|
|
18792
|
+
KEYWORD_OVERLAP_THRESHOLD = 0.8;
|
|
18793
|
+
MIN_SHARED_KEYWORDS = 3;
|
|
18794
|
+
STOP_WORDS = /* @__PURE__ */ new Set([
|
|
18795
|
+
"the",
|
|
18796
|
+
"a",
|
|
18797
|
+
"an",
|
|
18798
|
+
"is",
|
|
18799
|
+
"are",
|
|
18800
|
+
"was",
|
|
18801
|
+
"were",
|
|
18802
|
+
"be",
|
|
18803
|
+
"been",
|
|
18804
|
+
"being",
|
|
18805
|
+
"have",
|
|
18806
|
+
"has",
|
|
18807
|
+
"had",
|
|
18808
|
+
"do",
|
|
18809
|
+
"does",
|
|
18810
|
+
"did",
|
|
18811
|
+
"will",
|
|
18812
|
+
"would",
|
|
18813
|
+
"could",
|
|
18814
|
+
"should",
|
|
18815
|
+
"may",
|
|
18816
|
+
"might",
|
|
18817
|
+
"shall",
|
|
18818
|
+
"can",
|
|
18819
|
+
"to",
|
|
18820
|
+
"of",
|
|
18821
|
+
"in",
|
|
18822
|
+
"for",
|
|
18823
|
+
"on",
|
|
18824
|
+
"with",
|
|
18825
|
+
"at",
|
|
18826
|
+
"by",
|
|
18827
|
+
"from",
|
|
18828
|
+
"as",
|
|
18829
|
+
"into",
|
|
18830
|
+
"through",
|
|
18831
|
+
"and",
|
|
18832
|
+
"but",
|
|
18833
|
+
"or",
|
|
18834
|
+
"nor",
|
|
18835
|
+
"so",
|
|
18836
|
+
"yet",
|
|
18837
|
+
"this",
|
|
18838
|
+
"that",
|
|
18839
|
+
"these",
|
|
18840
|
+
"those",
|
|
18841
|
+
"it",
|
|
18842
|
+
"its",
|
|
18843
|
+
"not",
|
|
18844
|
+
"no"
|
|
18845
|
+
]);
|
|
18846
|
+
SUPERSEDABLE_TABLES = [
|
|
18847
|
+
{ table: "brain_decisions", textCol: "decision", type: "decision" },
|
|
18848
|
+
{ table: "brain_learnings", textCol: "insight", type: "learning" },
|
|
18849
|
+
{ table: "brain_patterns", textCol: "pattern", type: "pattern" },
|
|
18850
|
+
{ table: "brain_observations", textCol: "narrative", type: "observation" }
|
|
18851
|
+
];
|
|
18852
|
+
}
|
|
18853
|
+
});
|
|
18854
|
+
|
|
18651
18855
|
// packages/core/src/memory/patterns.ts
|
|
18652
18856
|
var patterns_exports = {};
|
|
18653
18857
|
__export(patterns_exports, {
|
|
@@ -18745,6 +18949,22 @@ async function storePattern(projectRoot, params) {
|
|
|
18745
18949
|
{ type: saved.type, impact: saved.impact ?? void 0 }
|
|
18746
18950
|
).catch(() => {
|
|
18747
18951
|
});
|
|
18952
|
+
detectSupersession(projectRoot, {
|
|
18953
|
+
id: saved.id,
|
|
18954
|
+
text: saved.pattern + " " + saved.context,
|
|
18955
|
+
createdAt: saved.extractedAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
18956
|
+
}).then((candidates) => {
|
|
18957
|
+
for (const candidate of candidates) {
|
|
18958
|
+
supersedeMemory(
|
|
18959
|
+
projectRoot,
|
|
18960
|
+
candidate.existingId,
|
|
18961
|
+
saved.id,
|
|
18962
|
+
"auto:pattern-supersedes \u2014 high overlap detected at store time"
|
|
18963
|
+
).catch(() => {
|
|
18964
|
+
});
|
|
18965
|
+
}
|
|
18966
|
+
}).catch(() => {
|
|
18967
|
+
});
|
|
18748
18968
|
return {
|
|
18749
18969
|
...saved,
|
|
18750
18970
|
examples: JSON.parse(saved.examplesJson || "[]")
|
|
@@ -18801,6 +19021,7 @@ var init_patterns = __esm({
|
|
|
18801
19021
|
init_brain_accessor();
|
|
18802
19022
|
init_graph_auto_populate();
|
|
18803
19023
|
init_quality_scoring();
|
|
19024
|
+
init_temporal_supersession();
|
|
18804
19025
|
}
|
|
18805
19026
|
});
|
|
18806
19027
|
|
|
@@ -18892,6 +19113,22 @@ async function storeLearning(projectRoot, params) {
|
|
|
18892
19113
|
{ source: saved.source, confidence: saved.confidence, actionable: saved.actionable }
|
|
18893
19114
|
).catch(() => {
|
|
18894
19115
|
});
|
|
19116
|
+
detectSupersession(projectRoot, {
|
|
19117
|
+
id: saved.id,
|
|
19118
|
+
text: saved.insight,
|
|
19119
|
+
createdAt: saved.createdAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
19120
|
+
}).then((candidates) => {
|
|
19121
|
+
for (const candidate of candidates) {
|
|
19122
|
+
supersedeMemory(
|
|
19123
|
+
projectRoot,
|
|
19124
|
+
candidate.existingId,
|
|
19125
|
+
saved.id,
|
|
19126
|
+
"auto:learning-supersedes \u2014 high overlap detected at store time"
|
|
19127
|
+
).catch(() => {
|
|
19128
|
+
});
|
|
19129
|
+
}
|
|
19130
|
+
}).catch(() => {
|
|
19131
|
+
});
|
|
18895
19132
|
return {
|
|
18896
19133
|
...saved,
|
|
18897
19134
|
applicableTypes: JSON.parse(saved.applicableTypesJson || "[]")
|
|
@@ -18952,6 +19189,7 @@ var init_learnings = __esm({
|
|
|
18952
19189
|
init_brain_accessor();
|
|
18953
19190
|
init_graph_auto_populate();
|
|
18954
19191
|
init_quality_scoring();
|
|
19192
|
+
init_temporal_supersession();
|
|
18955
19193
|
}
|
|
18956
19194
|
});
|
|
18957
19195
|
|
|
@@ -18990,16 +19228,6 @@ var init_mvi_helpers = __esm({
|
|
|
18990
19228
|
}
|
|
18991
19229
|
});
|
|
18992
19230
|
|
|
18993
|
-
// packages/core/src/store/typed-query.ts
|
|
18994
|
-
function typedAll(stmt, ...params) {
|
|
18995
|
-
return stmt.all(...params);
|
|
18996
|
-
}
|
|
18997
|
-
var init_typed_query = __esm({
|
|
18998
|
-
"packages/core/src/store/typed-query.ts"() {
|
|
18999
|
-
"use strict";
|
|
19000
|
-
}
|
|
19001
|
-
});
|
|
19002
|
-
|
|
19003
19231
|
// packages/core/src/memory/brain-similarity.ts
|
|
19004
19232
|
function parseIdPrefix(id) {
|
|
19005
19233
|
if (id.startsWith("D-") || /^D\d/.test(id)) return "decision";
|
|
@@ -20784,6 +21012,22 @@ async function storeDecision(projectRoot, params) {
|
|
|
20784
21012
|
}
|
|
20785
21013
|
} catch {
|
|
20786
21014
|
}
|
|
21015
|
+
detectSupersession(projectRoot, {
|
|
21016
|
+
id: saved.id,
|
|
21017
|
+
text: saved.decision + " " + saved.rationale,
|
|
21018
|
+
createdAt: saved.createdAt ?? (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19)
|
|
21019
|
+
}).then((candidates) => {
|
|
21020
|
+
for (const candidate of candidates) {
|
|
21021
|
+
supersedeMemory(
|
|
21022
|
+
projectRoot,
|
|
21023
|
+
candidate.existingId,
|
|
21024
|
+
saved.id,
|
|
21025
|
+
"auto:decision-supersedes \u2014 high overlap detected at store time"
|
|
21026
|
+
).catch(() => {
|
|
21027
|
+
});
|
|
21028
|
+
}
|
|
21029
|
+
}).catch(() => {
|
|
21030
|
+
});
|
|
20787
21031
|
return saved;
|
|
20788
21032
|
}
|
|
20789
21033
|
async function recallDecision(projectRoot, id) {
|
|
@@ -20836,6 +21080,7 @@ var init_decisions2 = __esm({
|
|
|
20836
21080
|
init_sqlite2();
|
|
20837
21081
|
init_graph_auto_populate();
|
|
20838
21082
|
init_quality_scoring();
|
|
21083
|
+
init_temporal_supersession();
|
|
20839
21084
|
}
|
|
20840
21085
|
});
|
|
20841
21086
|
|
|
@@ -41908,11 +42153,11 @@ var brain_consolidator_exports = {};
|
|
|
41908
42153
|
__export(brain_consolidator_exports, {
|
|
41909
42154
|
detectContradictions: () => detectContradictions
|
|
41910
42155
|
});
|
|
41911
|
-
function
|
|
42156
|
+
function extractKeywords2(text3) {
|
|
41912
42157
|
const words = text3.toLowerCase().replace(/[^a-z0-9\s\-_]/g, " ").split(/\s+/);
|
|
41913
42158
|
const keywords = /* @__PURE__ */ new Set();
|
|
41914
42159
|
for (const w of words) {
|
|
41915
|
-
if (w.length >= 4 && !
|
|
42160
|
+
if (w.length >= 4 && !STOP_WORDS2.has(w)) {
|
|
41916
42161
|
keywords.add(w);
|
|
41917
42162
|
}
|
|
41918
42163
|
}
|
|
@@ -41961,7 +42206,7 @@ async function detectContradictions(projectRoot) {
|
|
|
41961
42206
|
const keywordMap = /* @__PURE__ */ new Map();
|
|
41962
42207
|
const negationMap = /* @__PURE__ */ new Map();
|
|
41963
42208
|
for (const entry of entries) {
|
|
41964
|
-
keywordMap.set(entry.id,
|
|
42209
|
+
keywordMap.set(entry.id, extractKeywords2(entry.text));
|
|
41965
42210
|
negationMap.set(entry.id, findNegationMarkers(entry.text));
|
|
41966
42211
|
}
|
|
41967
42212
|
for (let i = 0; i < entries.length; i++) {
|
|
@@ -41975,7 +42220,7 @@ async function detectContradictions(projectRoot) {
|
|
|
41975
42220
|
const keywordsB = keywordMap.get(entryB.id);
|
|
41976
42221
|
const negationsB = negationMap.get(entryB.id);
|
|
41977
42222
|
const shared = keywordIntersection(keywordsA, keywordsB);
|
|
41978
|
-
if (shared.length <
|
|
42223
|
+
if (shared.length < MIN_SHARED_KEYWORDS2) continue;
|
|
41979
42224
|
const negationsOnlyInA = negationsA.filter((m) => !negationsB.includes(m));
|
|
41980
42225
|
const negationsOnlyInB = negationsB.filter((m) => !negationsA.includes(m));
|
|
41981
42226
|
const negationFlip = negationsOnlyInA.length > 0 || negationsOnlyInB.length > 0;
|
|
@@ -41993,8 +42238,8 @@ async function detectContradictions(projectRoot) {
|
|
|
41993
42238
|
sharedKeywords: shared.slice(0, 10),
|
|
41994
42239
|
negationMarkers: negMarkers.slice(0, 5)
|
|
41995
42240
|
});
|
|
41996
|
-
const nodeA =
|
|
41997
|
-
const nodeB =
|
|
42241
|
+
const nodeA = buildNodeId2(table, entryA.id);
|
|
42242
|
+
const nodeB = buildNodeId2(table, entryB.id);
|
|
41998
42243
|
try {
|
|
41999
42244
|
nativeDb.prepare(`
|
|
42000
42245
|
INSERT OR IGNORE INTO brain_page_edges
|
|
@@ -42023,7 +42268,7 @@ async function detectContradictions(projectRoot) {
|
|
|
42023
42268
|
}
|
|
42024
42269
|
return results;
|
|
42025
42270
|
}
|
|
42026
|
-
function
|
|
42271
|
+
function buildNodeId2(table, entryId) {
|
|
42027
42272
|
const typeMap = {
|
|
42028
42273
|
brain_observations: "observation",
|
|
42029
42274
|
brain_learnings: "learning",
|
|
@@ -42033,13 +42278,13 @@ function buildNodeId(table, entryId) {
|
|
|
42033
42278
|
const type = typeMap[table] ?? "entry";
|
|
42034
42279
|
return `${type}:${entryId}`;
|
|
42035
42280
|
}
|
|
42036
|
-
var
|
|
42281
|
+
var MIN_SHARED_KEYWORDS2, NEGATION_MARKERS, STOP_WORDS2;
|
|
42037
42282
|
var init_brain_consolidator = __esm({
|
|
42038
42283
|
"packages/core/src/memory/brain-consolidator.ts"() {
|
|
42039
42284
|
"use strict";
|
|
42040
42285
|
init_brain_sqlite();
|
|
42041
42286
|
init_typed_query();
|
|
42042
|
-
|
|
42287
|
+
MIN_SHARED_KEYWORDS2 = 3;
|
|
42043
42288
|
NEGATION_MARKERS = [
|
|
42044
42289
|
"not",
|
|
42045
42290
|
"never",
|
|
@@ -42060,7 +42305,7 @@ var init_brain_consolidator = __esm({
|
|
|
42060
42305
|
"undone",
|
|
42061
42306
|
"superseded"
|
|
42062
42307
|
];
|
|
42063
|
-
|
|
42308
|
+
STOP_WORDS2 = /* @__PURE__ */ new Set([
|
|
42064
42309
|
"the",
|
|
42065
42310
|
"a",
|
|
42066
42311
|
"an",
|
|
@@ -42115,6 +42360,390 @@ var init_brain_consolidator = __esm({
|
|
|
42115
42360
|
}
|
|
42116
42361
|
});
|
|
42117
42362
|
|
|
42363
|
+
// packages/core/src/memory/graph-memory-bridge.ts
|
|
42364
|
+
var graph_memory_bridge_exports = {};
|
|
42365
|
+
__export(graph_memory_bridge_exports, {
|
|
42366
|
+
autoLinkMemories: () => autoLinkMemories,
|
|
42367
|
+
linkMemoryToCode: () => linkMemoryToCode,
|
|
42368
|
+
listCodeLinks: () => listCodeLinks,
|
|
42369
|
+
queryCodeForMemory: () => queryCodeForMemory,
|
|
42370
|
+
queryMemoriesForCode: () => queryMemoriesForCode
|
|
42371
|
+
});
|
|
42372
|
+
function extractFilePaths(text3) {
|
|
42373
|
+
const paths = /* @__PURE__ */ new Set();
|
|
42374
|
+
for (const m of text3.matchAll(FILE_PATH_PATTERN)) {
|
|
42375
|
+
const p = m[1];
|
|
42376
|
+
if (p) paths.add(p);
|
|
42377
|
+
}
|
|
42378
|
+
return Array.from(paths);
|
|
42379
|
+
}
|
|
42380
|
+
function extractSymbolCandidates(text3) {
|
|
42381
|
+
const syms = /* @__PURE__ */ new Set();
|
|
42382
|
+
for (const m of text3.matchAll(SYMBOL_PATTERN)) {
|
|
42383
|
+
const s = m[1];
|
|
42384
|
+
if (s && s.length >= 4 && !SYMBOL_STOP_WORDS.has(s.toLowerCase())) {
|
|
42385
|
+
syms.add(s);
|
|
42386
|
+
}
|
|
42387
|
+
}
|
|
42388
|
+
return Array.from(syms);
|
|
42389
|
+
}
|
|
42390
|
+
function metadataText(metaJson) {
|
|
42391
|
+
if (!metaJson) return "";
|
|
42392
|
+
try {
|
|
42393
|
+
const obj = JSON.parse(metaJson);
|
|
42394
|
+
return Object.values(obj).filter((v) => typeof v === "string").join(" ");
|
|
42395
|
+
} catch {
|
|
42396
|
+
return "";
|
|
42397
|
+
}
|
|
42398
|
+
}
|
|
42399
|
+
async function linkMemoryToCode(projectRoot, memoryId, codeSymbol) {
|
|
42400
|
+
try {
|
|
42401
|
+
const brainDb = await getBrainDb(projectRoot);
|
|
42402
|
+
await getNexusDb();
|
|
42403
|
+
const nexusNative = getNexusNativeDb();
|
|
42404
|
+
if (!nexusNative) return false;
|
|
42405
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(codeSymbol);
|
|
42406
|
+
if (!nexusNode) return false;
|
|
42407
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
42408
|
+
const idParts = memoryId.split(":");
|
|
42409
|
+
const nodeType = idParts[0] ?? "observation";
|
|
42410
|
+
await brainDb.insert(brainPageNodes).values({
|
|
42411
|
+
id: memoryId,
|
|
42412
|
+
nodeType,
|
|
42413
|
+
label: memoryId,
|
|
42414
|
+
qualityScore: 0.5,
|
|
42415
|
+
contentHash: null,
|
|
42416
|
+
lastActivityAt: now,
|
|
42417
|
+
createdAt: now,
|
|
42418
|
+
updatedAt: now
|
|
42419
|
+
}).onConflictDoUpdate({
|
|
42420
|
+
target: brainPageNodes.id,
|
|
42421
|
+
set: { lastActivityAt: now, updatedAt: now }
|
|
42422
|
+
});
|
|
42423
|
+
await brainDb.insert(brainPageEdges).values({
|
|
42424
|
+
fromId: memoryId,
|
|
42425
|
+
toId: codeSymbol,
|
|
42426
|
+
edgeType: "code_reference",
|
|
42427
|
+
weight: 1,
|
|
42428
|
+
provenance: "manual",
|
|
42429
|
+
createdAt: now
|
|
42430
|
+
}).onConflictDoNothing();
|
|
42431
|
+
return true;
|
|
42432
|
+
} catch (err) {
|
|
42433
|
+
console.warn("[graph-memory-bridge] linkMemoryToCode failed:", err);
|
|
42434
|
+
return false;
|
|
42435
|
+
}
|
|
42436
|
+
}
|
|
42437
|
+
async function autoLinkMemories(projectRoot) {
|
|
42438
|
+
const result = { scanned: 0, linked: 0, alreadyLinked: 0, links: [] };
|
|
42439
|
+
try {
|
|
42440
|
+
await getBrainDb(projectRoot);
|
|
42441
|
+
const brainNative = getBrainNativeDb();
|
|
42442
|
+
await getNexusDb();
|
|
42443
|
+
const nexusNative = getNexusNativeDb();
|
|
42444
|
+
if (!brainNative || !nexusNative) return result;
|
|
42445
|
+
const brainNodes = typedAll(
|
|
42446
|
+
brainNative.prepare(`
|
|
42447
|
+
SELECT id, node_type, label, quality_score, metadata_json
|
|
42448
|
+
FROM brain_page_nodes
|
|
42449
|
+
WHERE node_type IN ('observation', 'decision', 'pattern', 'learning')
|
|
42450
|
+
AND quality_score >= 0.3
|
|
42451
|
+
ORDER BY quality_score DESC
|
|
42452
|
+
LIMIT 500
|
|
42453
|
+
`)
|
|
42454
|
+
);
|
|
42455
|
+
result.scanned = brainNodes.length;
|
|
42456
|
+
if (brainNodes.length === 0) return result;
|
|
42457
|
+
const nexusNodes2 = typedAll(
|
|
42458
|
+
nexusNative.prepare(`
|
|
42459
|
+
SELECT id, label, name, file_path, kind
|
|
42460
|
+
FROM nexus_nodes
|
|
42461
|
+
WHERE kind NOT IN ('community', 'process', 'folder')
|
|
42462
|
+
LIMIT 20000
|
|
42463
|
+
`)
|
|
42464
|
+
);
|
|
42465
|
+
if (nexusNodes2.length === 0) return result;
|
|
42466
|
+
const byFilePath = /* @__PURE__ */ new Map();
|
|
42467
|
+
const byNameExact = /* @__PURE__ */ new Map();
|
|
42468
|
+
const byNameLower = /* @__PURE__ */ new Map();
|
|
42469
|
+
for (const node of nexusNodes2) {
|
|
42470
|
+
if (node.file_path) {
|
|
42471
|
+
const fp = node.file_path.toLowerCase();
|
|
42472
|
+
const existing = byFilePath.get(fp) ?? [];
|
|
42473
|
+
existing.push(node);
|
|
42474
|
+
byFilePath.set(fp, existing);
|
|
42475
|
+
}
|
|
42476
|
+
if (node.name) {
|
|
42477
|
+
const exact = byNameExact.get(node.name) ?? [];
|
|
42478
|
+
exact.push(node);
|
|
42479
|
+
byNameExact.set(node.name, exact);
|
|
42480
|
+
const lower = node.name.toLowerCase();
|
|
42481
|
+
const fuzzy = byNameLower.get(lower) ?? [];
|
|
42482
|
+
fuzzy.push(node);
|
|
42483
|
+
byNameLower.set(lower, fuzzy);
|
|
42484
|
+
}
|
|
42485
|
+
}
|
|
42486
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
42487
|
+
const existingEdges = /* @__PURE__ */ new Set();
|
|
42488
|
+
const rawEdges = typedAll(
|
|
42489
|
+
brainNative.prepare(`
|
|
42490
|
+
SELECT from_id, to_id FROM brain_page_edges WHERE edge_type = 'code_reference'
|
|
42491
|
+
`)
|
|
42492
|
+
);
|
|
42493
|
+
for (const e of rawEdges) {
|
|
42494
|
+
existingEdges.add(`${e.from_id}|${e.to_id}`);
|
|
42495
|
+
}
|
|
42496
|
+
for (const brainNode of brainNodes) {
|
|
42497
|
+
const corpus = `${brainNode.label} ${metadataText(brainNode.metadata_json)}`;
|
|
42498
|
+
const filePaths = extractFilePaths(corpus);
|
|
42499
|
+
const symbolCandidates = extractSymbolCandidates(corpus);
|
|
42500
|
+
const candidates = [];
|
|
42501
|
+
for (const fp of filePaths) {
|
|
42502
|
+
const matches = byFilePath.get(fp.toLowerCase());
|
|
42503
|
+
if (matches) {
|
|
42504
|
+
for (const n of matches) {
|
|
42505
|
+
candidates.push({ nexusNode: n, strategy: "exact-file", weight: 1 });
|
|
42506
|
+
}
|
|
42507
|
+
}
|
|
42508
|
+
}
|
|
42509
|
+
for (const sym of symbolCandidates) {
|
|
42510
|
+
const exactMatches = byNameExact.get(sym);
|
|
42511
|
+
if (exactMatches) {
|
|
42512
|
+
for (const n of exactMatches) {
|
|
42513
|
+
candidates.push({ nexusNode: n, strategy: "exact-symbol", weight: 1 });
|
|
42514
|
+
}
|
|
42515
|
+
}
|
|
42516
|
+
}
|
|
42517
|
+
const exactSymSet = new Set(
|
|
42518
|
+
symbolCandidates.flatMap((s) => byNameExact.get(s) ?? []).map((n) => n.id)
|
|
42519
|
+
);
|
|
42520
|
+
for (const sym of symbolCandidates) {
|
|
42521
|
+
if (sym.length < 5) continue;
|
|
42522
|
+
const lower = sym.toLowerCase();
|
|
42523
|
+
const fuzzyMatches = byNameLower.get(lower);
|
|
42524
|
+
if (fuzzyMatches) {
|
|
42525
|
+
for (const n of fuzzyMatches) {
|
|
42526
|
+
if (!exactSymSet.has(n.id)) {
|
|
42527
|
+
candidates.push({ nexusNode: n, strategy: "fuzzy-symbol", weight: 0.6 });
|
|
42528
|
+
}
|
|
42529
|
+
}
|
|
42530
|
+
}
|
|
42531
|
+
}
|
|
42532
|
+
const bestByNexusId = /* @__PURE__ */ new Map();
|
|
42533
|
+
for (const c of candidates) {
|
|
42534
|
+
const existing = bestByNexusId.get(c.nexusNode.id);
|
|
42535
|
+
if (!existing || c.weight > existing.weight) {
|
|
42536
|
+
bestByNexusId.set(c.nexusNode.id, c);
|
|
42537
|
+
}
|
|
42538
|
+
}
|
|
42539
|
+
const sortedCandidates = Array.from(bestByNexusId.values()).sort((a, b) => b.weight - a.weight).slice(0, 10);
|
|
42540
|
+
for (const { nexusNode, strategy, weight } of sortedCandidates) {
|
|
42541
|
+
const edgeKey = `${brainNode.id}|${nexusNode.id}`;
|
|
42542
|
+
if (existingEdges.has(edgeKey)) {
|
|
42543
|
+
result.alreadyLinked++;
|
|
42544
|
+
continue;
|
|
42545
|
+
}
|
|
42546
|
+
brainNative.prepare(`
|
|
42547
|
+
INSERT OR IGNORE INTO brain_page_nodes
|
|
42548
|
+
(id, node_type, label, quality_score, content_hash, metadata_json, last_activity_at, created_at, updated_at)
|
|
42549
|
+
VALUES (?, ?, ?, ?, NULL, NULL, ?, ?, ?)
|
|
42550
|
+
`).run(
|
|
42551
|
+
brainNode.id,
|
|
42552
|
+
brainNode.node_type,
|
|
42553
|
+
brainNode.label,
|
|
42554
|
+
brainNode.quality_score,
|
|
42555
|
+
now,
|
|
42556
|
+
now,
|
|
42557
|
+
now
|
|
42558
|
+
);
|
|
42559
|
+
try {
|
|
42560
|
+
brainNative.prepare(`
|
|
42561
|
+
INSERT OR IGNORE INTO brain_page_edges
|
|
42562
|
+
(from_id, to_id, edge_type, weight, provenance, created_at)
|
|
42563
|
+
VALUES (?, ?, 'code_reference', ?, ?, ?)
|
|
42564
|
+
`).run(brainNode.id, nexusNode.id, weight, `auto:${strategy}`, now);
|
|
42565
|
+
existingEdges.add(edgeKey);
|
|
42566
|
+
result.linked++;
|
|
42567
|
+
result.links.push({
|
|
42568
|
+
brainNodeId: brainNode.id,
|
|
42569
|
+
nexusNodeId: nexusNode.id,
|
|
42570
|
+
nexusLabel: nexusNode.label,
|
|
42571
|
+
matchStrategy: strategy,
|
|
42572
|
+
weight
|
|
42573
|
+
});
|
|
42574
|
+
} catch (edgeErr) {
|
|
42575
|
+
console.warn("[graph-memory-bridge] edge insert failed:", edgeErr);
|
|
42576
|
+
}
|
|
42577
|
+
}
|
|
42578
|
+
}
|
|
42579
|
+
} catch (err) {
|
|
42580
|
+
console.warn("[graph-memory-bridge] autoLinkMemories failed:", err);
|
|
42581
|
+
}
|
|
42582
|
+
return result;
|
|
42583
|
+
}
|
|
42584
|
+
async function queryMemoriesForCode(projectRoot, symbol2) {
|
|
42585
|
+
const result = { nexusNodeId: symbol2, memories: [] };
|
|
42586
|
+
try {
|
|
42587
|
+
await getBrainDb(projectRoot);
|
|
42588
|
+
const brainNative = getBrainNativeDb();
|
|
42589
|
+
if (!brainNative) return result;
|
|
42590
|
+
const rows = typedAll(
|
|
42591
|
+
brainNative.prepare(`
|
|
42592
|
+
SELECT n.id, n.node_type, n.label, n.quality_score,
|
|
42593
|
+
e.weight, e.provenance
|
|
42594
|
+
FROM brain_page_edges e
|
|
42595
|
+
JOIN brain_page_nodes n ON n.id = e.from_id
|
|
42596
|
+
WHERE e.to_id = ?
|
|
42597
|
+
AND e.edge_type = 'code_reference'
|
|
42598
|
+
ORDER BY e.weight DESC, n.quality_score DESC
|
|
42599
|
+
LIMIT 50
|
|
42600
|
+
`),
|
|
42601
|
+
symbol2
|
|
42602
|
+
);
|
|
42603
|
+
result.memories = rows.map((r) => ({
|
|
42604
|
+
nodeId: r.id,
|
|
42605
|
+
nodeType: r.node_type,
|
|
42606
|
+
label: r.label,
|
|
42607
|
+
qualityScore: r.quality_score,
|
|
42608
|
+
edgeWeight: r.weight,
|
|
42609
|
+
matchStrategy: r.provenance?.replace("auto:", "") ?? "manual"
|
|
42610
|
+
}));
|
|
42611
|
+
} catch (err) {
|
|
42612
|
+
console.warn("[graph-memory-bridge] queryMemoriesForCode failed:", err);
|
|
42613
|
+
}
|
|
42614
|
+
return result;
|
|
42615
|
+
}
|
|
42616
|
+
async function queryCodeForMemory(projectRoot, memoryId) {
|
|
42617
|
+
const result = { brainNodeId: memoryId, codeNodes: [] };
|
|
42618
|
+
try {
|
|
42619
|
+
await getBrainDb(projectRoot);
|
|
42620
|
+
const brainNative = getBrainNativeDb();
|
|
42621
|
+
await getNexusDb();
|
|
42622
|
+
const nexusNative = getNexusNativeDb();
|
|
42623
|
+
if (!brainNative || !nexusNative) return result;
|
|
42624
|
+
const brainEdges = typedAll(
|
|
42625
|
+
brainNative.prepare(`
|
|
42626
|
+
SELECT to_id, weight, provenance
|
|
42627
|
+
FROM brain_page_edges
|
|
42628
|
+
WHERE from_id = ?
|
|
42629
|
+
AND edge_type = 'code_reference'
|
|
42630
|
+
ORDER BY weight DESC
|
|
42631
|
+
LIMIT 50
|
|
42632
|
+
`),
|
|
42633
|
+
memoryId
|
|
42634
|
+
);
|
|
42635
|
+
if (brainEdges.length === 0) return result;
|
|
42636
|
+
for (const edge of brainEdges) {
|
|
42637
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(edge.to_id);
|
|
42638
|
+
if (nexusNode) {
|
|
42639
|
+
result.codeNodes.push({
|
|
42640
|
+
nexusNodeId: nexusNode.id,
|
|
42641
|
+
label: nexusNode.label,
|
|
42642
|
+
filePath: nexusNode.file_path,
|
|
42643
|
+
kind: nexusNode.kind,
|
|
42644
|
+
edgeWeight: edge.weight,
|
|
42645
|
+
matchStrategy: edge.provenance?.replace("auto:", "") ?? "manual"
|
|
42646
|
+
});
|
|
42647
|
+
}
|
|
42648
|
+
}
|
|
42649
|
+
} catch (err) {
|
|
42650
|
+
console.warn("[graph-memory-bridge] queryCodeForMemory failed:", err);
|
|
42651
|
+
}
|
|
42652
|
+
return result;
|
|
42653
|
+
}
|
|
42654
|
+
async function listCodeLinks(projectRoot, limit = 100) {
|
|
42655
|
+
const entries = [];
|
|
42656
|
+
try {
|
|
42657
|
+
await getBrainDb(projectRoot);
|
|
42658
|
+
const brainNative = getBrainNativeDb();
|
|
42659
|
+
await getNexusDb();
|
|
42660
|
+
const nexusNative = getNexusNativeDb();
|
|
42661
|
+
if (!brainNative || !nexusNative) return entries;
|
|
42662
|
+
const rows = typedAll(
|
|
42663
|
+
brainNative.prepare(`
|
|
42664
|
+
SELECT e.from_id, e.to_id, e.weight, e.created_at,
|
|
42665
|
+
n.node_type, n.label
|
|
42666
|
+
FROM brain_page_edges e
|
|
42667
|
+
JOIN brain_page_nodes n ON n.id = e.from_id
|
|
42668
|
+
WHERE e.edge_type = 'code_reference'
|
|
42669
|
+
ORDER BY e.weight DESC, e.created_at DESC
|
|
42670
|
+
LIMIT ?
|
|
42671
|
+
`),
|
|
42672
|
+
limit
|
|
42673
|
+
);
|
|
42674
|
+
for (const row of rows) {
|
|
42675
|
+
const nexusNode = nexusNative.prepare("SELECT id, label, file_path, kind FROM nexus_nodes WHERE id = ? LIMIT 1").get(row.to_id);
|
|
42676
|
+
entries.push({
|
|
42677
|
+
brainNodeId: row.from_id,
|
|
42678
|
+
brainNodeType: row.node_type,
|
|
42679
|
+
brainNodeLabel: row.label,
|
|
42680
|
+
nexusNodeId: row.to_id,
|
|
42681
|
+
nexusNodeLabel: nexusNode?.label ?? row.to_id,
|
|
42682
|
+
filePath: nexusNode?.file_path ?? null,
|
|
42683
|
+
kind: nexusNode?.kind ?? "unknown",
|
|
42684
|
+
weight: row.weight,
|
|
42685
|
+
createdAt: row.created_at
|
|
42686
|
+
});
|
|
42687
|
+
}
|
|
42688
|
+
} catch (err) {
|
|
42689
|
+
console.warn("[graph-memory-bridge] listCodeLinks failed:", err);
|
|
42690
|
+
}
|
|
42691
|
+
return entries;
|
|
42692
|
+
}
|
|
42693
|
+
var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
|
|
42694
|
+
var init_graph_memory_bridge = __esm({
|
|
42695
|
+
"packages/core/src/memory/graph-memory-bridge.ts"() {
|
|
42696
|
+
"use strict";
|
|
42697
|
+
init_brain_schema();
|
|
42698
|
+
init_brain_sqlite();
|
|
42699
|
+
init_nexus_sqlite();
|
|
42700
|
+
init_typed_query();
|
|
42701
|
+
FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
|
|
42702
|
+
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;
|
|
42703
|
+
SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
|
|
42704
|
+
"true",
|
|
42705
|
+
"false",
|
|
42706
|
+
"null",
|
|
42707
|
+
"undefined",
|
|
42708
|
+
"const",
|
|
42709
|
+
"async",
|
|
42710
|
+
"await",
|
|
42711
|
+
"return",
|
|
42712
|
+
"export",
|
|
42713
|
+
"import",
|
|
42714
|
+
"from",
|
|
42715
|
+
"type",
|
|
42716
|
+
"interface",
|
|
42717
|
+
"function",
|
|
42718
|
+
"class",
|
|
42719
|
+
"this",
|
|
42720
|
+
"super",
|
|
42721
|
+
"extends",
|
|
42722
|
+
"implements",
|
|
42723
|
+
"with",
|
|
42724
|
+
"that",
|
|
42725
|
+
"then",
|
|
42726
|
+
"when",
|
|
42727
|
+
"have",
|
|
42728
|
+
"been",
|
|
42729
|
+
"will",
|
|
42730
|
+
"should",
|
|
42731
|
+
"could",
|
|
42732
|
+
"would",
|
|
42733
|
+
"error",
|
|
42734
|
+
"result",
|
|
42735
|
+
"value",
|
|
42736
|
+
"data",
|
|
42737
|
+
"info",
|
|
42738
|
+
"note",
|
|
42739
|
+
"todo",
|
|
42740
|
+
"done",
|
|
42741
|
+
"fail",
|
|
42742
|
+
"pass"
|
|
42743
|
+
]);
|
|
42744
|
+
}
|
|
42745
|
+
});
|
|
42746
|
+
|
|
42118
42747
|
// packages/core/src/memory/brain-lifecycle.ts
|
|
42119
42748
|
var brain_lifecycle_exports = {};
|
|
42120
42749
|
__export(brain_lifecycle_exports, {
|
|
@@ -42148,11 +42777,11 @@ async function applyTemporalDecay(projectRoot, options) {
|
|
|
42148
42777
|
tablesProcessed: ["brain_learnings"]
|
|
42149
42778
|
};
|
|
42150
42779
|
}
|
|
42151
|
-
function
|
|
42780
|
+
function extractKeywords3(text3) {
|
|
42152
42781
|
const words = text3.toLowerCase().replace(/[^a-z0-9\s-]/g, "").split(/\s+/);
|
|
42153
42782
|
const keywords = /* @__PURE__ */ new Set();
|
|
42154
42783
|
for (const w of words) {
|
|
42155
|
-
if (w.length >= 4 && !
|
|
42784
|
+
if (w.length >= 4 && !STOP_WORDS3.has(w)) {
|
|
42156
42785
|
keywords.add(w);
|
|
42157
42786
|
}
|
|
42158
42787
|
}
|
|
@@ -42190,7 +42819,7 @@ async function consolidateMemories(projectRoot, options) {
|
|
|
42190
42819
|
}
|
|
42191
42820
|
const entries = oldObservations.map((obs) => ({
|
|
42192
42821
|
...obs,
|
|
42193
|
-
keywords:
|
|
42822
|
+
keywords: extractKeywords3(`${obs.title} ${obs.narrative ?? ""}`),
|
|
42194
42823
|
clustered: false
|
|
42195
42824
|
}));
|
|
42196
42825
|
const clusters = [];
|
|
@@ -42414,6 +43043,13 @@ async function runConsolidation(projectRoot) {
|
|
|
42414
43043
|
} catch (err) {
|
|
42415
43044
|
console.warn("[consolidation] Step 7 summary generation failed:", err);
|
|
42416
43045
|
}
|
|
43046
|
+
try {
|
|
43047
|
+
const { autoLinkMemories: autoLinkMemories2 } = await Promise.resolve().then(() => (init_graph_memory_bridge(), graph_memory_bridge_exports));
|
|
43048
|
+
const bridgeResult = await autoLinkMemories2(projectRoot);
|
|
43049
|
+
result.graphLinksCreated = bridgeResult.linked;
|
|
43050
|
+
} catch (err) {
|
|
43051
|
+
console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
|
|
43052
|
+
}
|
|
42417
43053
|
return result;
|
|
42418
43054
|
}
|
|
42419
43055
|
async function deduplicateByEmbedding(projectRoot) {
|
|
@@ -42592,13 +43228,13 @@ async function strengthenCoRetrievedEdges(projectRoot) {
|
|
|
42592
43228
|
}
|
|
42593
43229
|
return strengthened;
|
|
42594
43230
|
}
|
|
42595
|
-
var
|
|
43231
|
+
var STOP_WORDS3;
|
|
42596
43232
|
var init_brain_lifecycle = __esm({
|
|
42597
43233
|
"packages/core/src/memory/brain-lifecycle.ts"() {
|
|
42598
43234
|
"use strict";
|
|
42599
43235
|
init_brain_accessor();
|
|
42600
43236
|
init_typed_query();
|
|
42601
|
-
|
|
43237
|
+
STOP_WORDS3 = /* @__PURE__ */ new Set([
|
|
42602
43238
|
"the",
|
|
42603
43239
|
"a",
|
|
42604
43240
|
"an",
|
|
@@ -43203,6 +43839,358 @@ var init_session_hooks = __esm({
|
|
|
43203
43839
|
}
|
|
43204
43840
|
});
|
|
43205
43841
|
|
|
43842
|
+
// packages/core/src/memory/quality-feedback.ts
|
|
43843
|
+
var quality_feedback_exports = {};
|
|
43844
|
+
__export(quality_feedback_exports, {
|
|
43845
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
43846
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
43847
|
+
trackMemoryUsage: () => trackMemoryUsage
|
|
43848
|
+
});
|
|
43849
|
+
async function ensureUsageLogTable(projectRoot) {
|
|
43850
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
43851
|
+
await getBrainDb2(projectRoot);
|
|
43852
|
+
const nativeDb = getBrainNativeDb2();
|
|
43853
|
+
if (!nativeDb) return;
|
|
43854
|
+
try {
|
|
43855
|
+
nativeDb.prepare(
|
|
43856
|
+
`CREATE TABLE IF NOT EXISTS brain_usage_log (
|
|
43857
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
43858
|
+
entry_id TEXT NOT NULL,
|
|
43859
|
+
task_id TEXT,
|
|
43860
|
+
used INTEGER NOT NULL DEFAULT 0,
|
|
43861
|
+
outcome TEXT NOT NULL DEFAULT 'unknown',
|
|
43862
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
43863
|
+
)`
|
|
43864
|
+
).run();
|
|
43865
|
+
nativeDb.prepare(
|
|
43866
|
+
`CREATE INDEX IF NOT EXISTS idx_brain_usage_log_entry_id
|
|
43867
|
+
ON brain_usage_log(entry_id)`
|
|
43868
|
+
).run();
|
|
43869
|
+
nativeDb.prepare(
|
|
43870
|
+
`CREATE INDEX IF NOT EXISTS idx_brain_usage_log_task_id
|
|
43871
|
+
ON brain_usage_log(task_id)`
|
|
43872
|
+
).run();
|
|
43873
|
+
} catch {
|
|
43874
|
+
}
|
|
43875
|
+
}
|
|
43876
|
+
async function ensurePruneCandidateColumn(projectRoot) {
|
|
43877
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
43878
|
+
await getBrainDb2(projectRoot);
|
|
43879
|
+
const nativeDb = getBrainNativeDb2();
|
|
43880
|
+
if (!nativeDb) return;
|
|
43881
|
+
const tables = [
|
|
43882
|
+
"brain_decisions",
|
|
43883
|
+
"brain_patterns",
|
|
43884
|
+
"brain_learnings",
|
|
43885
|
+
"brain_observations"
|
|
43886
|
+
];
|
|
43887
|
+
for (const tbl of tables) {
|
|
43888
|
+
try {
|
|
43889
|
+
nativeDb.prepare(`ALTER TABLE ${tbl} ADD COLUMN prune_candidate INTEGER DEFAULT 0`).run();
|
|
43890
|
+
} catch {
|
|
43891
|
+
}
|
|
43892
|
+
}
|
|
43893
|
+
}
|
|
43894
|
+
async function trackMemoryUsage(projectRoot, memoryId, used, taskId, outcome = "unknown") {
|
|
43895
|
+
if (!memoryId?.trim()) return;
|
|
43896
|
+
await ensureUsageLogTable(projectRoot);
|
|
43897
|
+
const { getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
43898
|
+
const nativeDb = getBrainNativeDb2();
|
|
43899
|
+
if (!nativeDb) return;
|
|
43900
|
+
const now = (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
|
|
43901
|
+
try {
|
|
43902
|
+
nativeDb.prepare(
|
|
43903
|
+
`INSERT INTO brain_usage_log (entry_id, task_id, used, outcome, created_at)
|
|
43904
|
+
VALUES (?, ?, ?, ?, ?)`
|
|
43905
|
+
).run(memoryId, taskId ?? null, used ? 1 : 0, outcome, now);
|
|
43906
|
+
} catch {
|
|
43907
|
+
}
|
|
43908
|
+
}
|
|
43909
|
+
function tableForId(id) {
|
|
43910
|
+
if (id.startsWith("D-") || /^D\d/.test(id)) return "brain_decisions";
|
|
43911
|
+
if (id.startsWith("P-") || /^P\d/.test(id)) return "brain_patterns";
|
|
43912
|
+
if (id.startsWith("L-") || /^L\d/.test(id)) return "brain_learnings";
|
|
43913
|
+
if (id.startsWith("O-") || id.startsWith("CM-") || /^O/.test(id)) return "brain_observations";
|
|
43914
|
+
return null;
|
|
43915
|
+
}
|
|
43916
|
+
function applyQualityDelta(nativeDb, table, id, delta, now) {
|
|
43917
|
+
if (!nativeDb) return;
|
|
43918
|
+
try {
|
|
43919
|
+
nativeDb.prepare(
|
|
43920
|
+
`UPDATE ${table}
|
|
43921
|
+
SET quality_score = MAX(0.0, MIN(1.0, COALESCE(quality_score, 0.5) + ?)),
|
|
43922
|
+
updated_at = ?
|
|
43923
|
+
WHERE id = ?`
|
|
43924
|
+
).run(delta, now, id);
|
|
43925
|
+
} catch {
|
|
43926
|
+
}
|
|
43927
|
+
}
|
|
43928
|
+
async function correlateOutcomes(projectRoot) {
|
|
43929
|
+
await ensureUsageLogTable(projectRoot);
|
|
43930
|
+
await ensurePruneCandidateColumn(projectRoot);
|
|
43931
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
43932
|
+
await getBrainDb2(projectRoot);
|
|
43933
|
+
const nativeDb = getBrainNativeDb2();
|
|
43934
|
+
const ranAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
43935
|
+
if (!nativeDb) {
|
|
43936
|
+
return { boosted: 0, penalized: 0, flaggedForPruning: 0, ranAt };
|
|
43937
|
+
}
|
|
43938
|
+
const now = ranAt.replace("T", " ").slice(0, 19);
|
|
43939
|
+
let boosted = 0;
|
|
43940
|
+
let penalized = 0;
|
|
43941
|
+
let usageRows = [];
|
|
43942
|
+
try {
|
|
43943
|
+
usageRows = typedAll(
|
|
43944
|
+
nativeDb.prepare(
|
|
43945
|
+
`SELECT entry_id, outcome, SUM(used) AS used_count
|
|
43946
|
+
FROM brain_usage_log
|
|
43947
|
+
WHERE outcome IN ('success', 'failure')
|
|
43948
|
+
GROUP BY entry_id, outcome`
|
|
43949
|
+
)
|
|
43950
|
+
);
|
|
43951
|
+
} catch {
|
|
43952
|
+
usageRows = [];
|
|
43953
|
+
}
|
|
43954
|
+
for (const row of usageRows) {
|
|
43955
|
+
const table = tableForId(row.entry_id);
|
|
43956
|
+
if (!table) continue;
|
|
43957
|
+
if (row.outcome === "success" && row.used_count > 0) {
|
|
43958
|
+
applyQualityDelta(nativeDb, table, row.entry_id, 0.05, now);
|
|
43959
|
+
boosted++;
|
|
43960
|
+
} else if (row.outcome === "failure" && row.used_count > 0) {
|
|
43961
|
+
applyQualityDelta(nativeDb, table, row.entry_id, -0.05, now);
|
|
43962
|
+
penalized++;
|
|
43963
|
+
}
|
|
43964
|
+
}
|
|
43965
|
+
const cutoffDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1e3).toISOString().replace("T", " ").slice(0, 19);
|
|
43966
|
+
let flaggedForPruning = 0;
|
|
43967
|
+
const pruneTargetTables = [
|
|
43968
|
+
{ table: "brain_decisions", dateCol: "created_at" },
|
|
43969
|
+
{ table: "brain_patterns", dateCol: "extracted_at" },
|
|
43970
|
+
{ table: "brain_learnings", dateCol: "created_at" },
|
|
43971
|
+
{ table: "brain_observations", dateCol: "created_at" }
|
|
43972
|
+
];
|
|
43973
|
+
for (const { table, dateCol } of pruneTargetTables) {
|
|
43974
|
+
try {
|
|
43975
|
+
const result = nativeDb.prepare(
|
|
43976
|
+
`UPDATE ${table}
|
|
43977
|
+
SET prune_candidate = 1
|
|
43978
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
43979
|
+
AND ${dateCol} < ?`
|
|
43980
|
+
).run(cutoffDate);
|
|
43981
|
+
flaggedForPruning += result.changes ?? 0;
|
|
43982
|
+
} catch {
|
|
43983
|
+
}
|
|
43984
|
+
}
|
|
43985
|
+
return { boosted, penalized, flaggedForPruning, ranAt };
|
|
43986
|
+
}
|
|
43987
|
+
async function getMemoryQualityReport(projectRoot) {
|
|
43988
|
+
await ensureUsageLogTable(projectRoot);
|
|
43989
|
+
const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
|
|
43990
|
+
await getBrainDb2(projectRoot);
|
|
43991
|
+
const nativeDb = getBrainNativeDb2();
|
|
43992
|
+
const emptyReport = {
|
|
43993
|
+
totalRetrievals: 0,
|
|
43994
|
+
uniqueEntriesRetrieved: 0,
|
|
43995
|
+
usageRate: 0,
|
|
43996
|
+
topRetrieved: [],
|
|
43997
|
+
neverRetrieved: [],
|
|
43998
|
+
qualityDistribution: { low: 0, medium: 0, high: 0 },
|
|
43999
|
+
tierDistribution: { short: 0, medium: 0, long: 0, unknown: 0 },
|
|
44000
|
+
noiseRatio: 0
|
|
44001
|
+
};
|
|
44002
|
+
if (!nativeDb) return emptyReport;
|
|
44003
|
+
let totalRetrievals = 0;
|
|
44004
|
+
let uniqueEntriesRetrieved = 0;
|
|
44005
|
+
try {
|
|
44006
|
+
const logCount = typedAll(
|
|
44007
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_retrieval_log")
|
|
44008
|
+
);
|
|
44009
|
+
totalRetrievals = logCount[0]?.cnt ?? 0;
|
|
44010
|
+
const uniqueCount = typedAll(
|
|
44011
|
+
nativeDb.prepare(
|
|
44012
|
+
`SELECT COUNT(DISTINCT value) AS cnt
|
|
44013
|
+
FROM brain_retrieval_log,
|
|
44014
|
+
json_each('["' || replace(entry_ids, ',', '","') || '"]')`
|
|
44015
|
+
)
|
|
44016
|
+
);
|
|
44017
|
+
uniqueEntriesRetrieved = uniqueCount[0]?.cnt ?? 0;
|
|
44018
|
+
} catch {
|
|
44019
|
+
}
|
|
44020
|
+
let usageRate = 0;
|
|
44021
|
+
try {
|
|
44022
|
+
const totalUsage = typedAll(
|
|
44023
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_usage_log")
|
|
44024
|
+
);
|
|
44025
|
+
const usedCount = typedAll(
|
|
44026
|
+
nativeDb.prepare("SELECT COUNT(*) AS cnt FROM brain_usage_log WHERE used = 1")
|
|
44027
|
+
);
|
|
44028
|
+
const total = totalUsage[0]?.cnt ?? 0;
|
|
44029
|
+
const used = usedCount[0]?.cnt ?? 0;
|
|
44030
|
+
usageRate = total > 0 ? used / total : 0;
|
|
44031
|
+
} catch {
|
|
44032
|
+
}
|
|
44033
|
+
const topRetrieved = [];
|
|
44034
|
+
try {
|
|
44035
|
+
const rows = typedAll(
|
|
44036
|
+
nativeDb.prepare(
|
|
44037
|
+
`SELECT id,
|
|
44038
|
+
'decision' AS type,
|
|
44039
|
+
decision AS title,
|
|
44040
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
44041
|
+
FROM brain_decisions
|
|
44042
|
+
UNION ALL
|
|
44043
|
+
SELECT id,
|
|
44044
|
+
'pattern' AS type,
|
|
44045
|
+
pattern AS title,
|
|
44046
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
44047
|
+
FROM brain_patterns
|
|
44048
|
+
UNION ALL
|
|
44049
|
+
SELECT id,
|
|
44050
|
+
'learning' AS type,
|
|
44051
|
+
insight AS title,
|
|
44052
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
44053
|
+
FROM brain_learnings
|
|
44054
|
+
UNION ALL
|
|
44055
|
+
SELECT id,
|
|
44056
|
+
'observation' AS type,
|
|
44057
|
+
title AS title,
|
|
44058
|
+
COALESCE(citation_count, 0) AS citation_count
|
|
44059
|
+
FROM brain_observations
|
|
44060
|
+
ORDER BY citation_count DESC
|
|
44061
|
+
LIMIT 10`
|
|
44062
|
+
)
|
|
44063
|
+
);
|
|
44064
|
+
for (const r of rows) {
|
|
44065
|
+
topRetrieved.push({
|
|
44066
|
+
id: r.id,
|
|
44067
|
+
type: r.type,
|
|
44068
|
+
title: String(r.title ?? "").slice(0, 120),
|
|
44069
|
+
citationCount: r.citation_count
|
|
44070
|
+
});
|
|
44071
|
+
}
|
|
44072
|
+
} catch {
|
|
44073
|
+
}
|
|
44074
|
+
const neverRetrieved = [];
|
|
44075
|
+
try {
|
|
44076
|
+
const rows = typedAll(
|
|
44077
|
+
nativeDb.prepare(
|
|
44078
|
+
`SELECT id,
|
|
44079
|
+
'decision' AS type,
|
|
44080
|
+
decision AS title,
|
|
44081
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
44082
|
+
FROM brain_decisions
|
|
44083
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
44084
|
+
UNION ALL
|
|
44085
|
+
SELECT id,
|
|
44086
|
+
'pattern' AS type,
|
|
44087
|
+
pattern AS title,
|
|
44088
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
44089
|
+
FROM brain_patterns
|
|
44090
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
44091
|
+
UNION ALL
|
|
44092
|
+
SELECT id,
|
|
44093
|
+
'learning' AS type,
|
|
44094
|
+
insight AS title,
|
|
44095
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
44096
|
+
FROM brain_learnings
|
|
44097
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
44098
|
+
UNION ALL
|
|
44099
|
+
SELECT id,
|
|
44100
|
+
'observation' AS type,
|
|
44101
|
+
title AS title,
|
|
44102
|
+
COALESCE(quality_score, 0.5) AS quality_score
|
|
44103
|
+
FROM brain_observations
|
|
44104
|
+
WHERE COALESCE(citation_count, 0) = 0
|
|
44105
|
+
ORDER BY quality_score ASC
|
|
44106
|
+
LIMIT 10`
|
|
44107
|
+
)
|
|
44108
|
+
);
|
|
44109
|
+
for (const r of rows) {
|
|
44110
|
+
neverRetrieved.push({
|
|
44111
|
+
id: r.id,
|
|
44112
|
+
type: r.type,
|
|
44113
|
+
title: String(r.title ?? "").slice(0, 120),
|
|
44114
|
+
qualityScore: r.quality_score
|
|
44115
|
+
});
|
|
44116
|
+
}
|
|
44117
|
+
} catch {
|
|
44118
|
+
}
|
|
44119
|
+
let qualityDistribution = { low: 0, medium: 0, high: 0 };
|
|
44120
|
+
try {
|
|
44121
|
+
const rows = typedAll(
|
|
44122
|
+
nativeDb.prepare(
|
|
44123
|
+
`SELECT
|
|
44124
|
+
SUM(CASE WHEN qs < 0.3 THEN 1 ELSE 0 END) AS low,
|
|
44125
|
+
SUM(CASE WHEN qs >= 0.3 AND qs <= 0.6 THEN 1 ELSE 0 END) AS medium,
|
|
44126
|
+
SUM(CASE WHEN qs > 0.6 THEN 1 ELSE 0 END) AS high
|
|
44127
|
+
FROM (
|
|
44128
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_decisions
|
|
44129
|
+
UNION ALL
|
|
44130
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_patterns
|
|
44131
|
+
UNION ALL
|
|
44132
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_learnings
|
|
44133
|
+
UNION ALL
|
|
44134
|
+
SELECT COALESCE(quality_score, 0.5) AS qs FROM brain_observations
|
|
44135
|
+
)`
|
|
44136
|
+
)
|
|
44137
|
+
);
|
|
44138
|
+
if (rows[0]) {
|
|
44139
|
+
qualityDistribution = {
|
|
44140
|
+
low: rows[0].low ?? 0,
|
|
44141
|
+
medium: rows[0].medium ?? 0,
|
|
44142
|
+
high: rows[0].high ?? 0
|
|
44143
|
+
};
|
|
44144
|
+
}
|
|
44145
|
+
} catch {
|
|
44146
|
+
}
|
|
44147
|
+
const tierDistribution = { short: 0, medium: 0, long: 0, unknown: 0 };
|
|
44148
|
+
try {
|
|
44149
|
+
const rows = typedAll(
|
|
44150
|
+
nativeDb.prepare(
|
|
44151
|
+
`SELECT memory_tier AS tier, COUNT(*) AS cnt
|
|
44152
|
+
FROM (
|
|
44153
|
+
SELECT memory_tier FROM brain_decisions
|
|
44154
|
+
UNION ALL
|
|
44155
|
+
SELECT memory_tier FROM brain_patterns
|
|
44156
|
+
UNION ALL
|
|
44157
|
+
SELECT memory_tier FROM brain_learnings
|
|
44158
|
+
UNION ALL
|
|
44159
|
+
SELECT memory_tier FROM brain_observations
|
|
44160
|
+
)
|
|
44161
|
+
GROUP BY memory_tier`
|
|
44162
|
+
)
|
|
44163
|
+
);
|
|
44164
|
+
for (const r of rows) {
|
|
44165
|
+
const tier = r.tier?.toLowerCase() ?? "unknown";
|
|
44166
|
+
if (tier === "short" || tier === "medium" || tier === "long") {
|
|
44167
|
+
tierDistribution[tier] += r.cnt;
|
|
44168
|
+
} else {
|
|
44169
|
+
tierDistribution.unknown += r.cnt;
|
|
44170
|
+
}
|
|
44171
|
+
}
|
|
44172
|
+
} catch {
|
|
44173
|
+
}
|
|
44174
|
+
const totalEntries = qualityDistribution.low + qualityDistribution.medium + qualityDistribution.high;
|
|
44175
|
+
const noiseRatio = totalEntries > 0 ? qualityDistribution.low / totalEntries : 0;
|
|
44176
|
+
return {
|
|
44177
|
+
totalRetrievals,
|
|
44178
|
+
uniqueEntriesRetrieved,
|
|
44179
|
+
usageRate,
|
|
44180
|
+
topRetrieved,
|
|
44181
|
+
neverRetrieved,
|
|
44182
|
+
qualityDistribution,
|
|
44183
|
+
tierDistribution,
|
|
44184
|
+
noiseRatio
|
|
44185
|
+
};
|
|
44186
|
+
}
|
|
44187
|
+
var init_quality_feedback = __esm({
|
|
44188
|
+
"packages/core/src/memory/quality-feedback.ts"() {
|
|
44189
|
+
"use strict";
|
|
44190
|
+
init_typed_query();
|
|
44191
|
+
}
|
|
44192
|
+
});
|
|
44193
|
+
|
|
43206
44194
|
// packages/core/src/hooks/handlers/task-hooks.ts
|
|
43207
44195
|
async function handleToolStart(projectRoot, payload) {
|
|
43208
44196
|
const { observeBrain: observeBrain2 } = await Promise.resolve().then(() => (init_brain_retrieval(), brain_retrieval_exports));
|
|
@@ -43236,6 +44224,13 @@ async function handleToolComplete(projectRoot, payload) {
|
|
|
43236
44224
|
} catch {
|
|
43237
44225
|
}
|
|
43238
44226
|
});
|
|
44227
|
+
setImmediate(async () => {
|
|
44228
|
+
try {
|
|
44229
|
+
const { correlateOutcomes: correlateOutcomes2 } = await Promise.resolve().then(() => (init_quality_feedback(), quality_feedback_exports));
|
|
44230
|
+
await correlateOutcomes2(projectRoot);
|
|
44231
|
+
} catch {
|
|
44232
|
+
}
|
|
44233
|
+
});
|
|
43239
44234
|
await maybeRefreshMemoryBridge(projectRoot);
|
|
43240
44235
|
}
|
|
43241
44236
|
var init_task_hooks = __esm({
|
|
@@ -51567,6 +52562,19 @@ async function completeTask(options, cwd, accessor) {
|
|
|
51567
52562
|
})()
|
|
51568
52563
|
).catch(() => {
|
|
51569
52564
|
});
|
|
52565
|
+
try {
|
|
52566
|
+
const { hooks: hooks2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
52567
|
+
await hooks2.dispatch("PostToolUse", cwd ?? process.cwd(), {
|
|
52568
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52569
|
+
taskId: options.taskId,
|
|
52570
|
+
taskTitle: task.title,
|
|
52571
|
+
previousStatus: before.status,
|
|
52572
|
+
newStatus: "done",
|
|
52573
|
+
unblockedCount: unblockedTasks.length
|
|
52574
|
+
}).catch(() => {
|
|
52575
|
+
});
|
|
52576
|
+
} catch {
|
|
52577
|
+
}
|
|
51570
52578
|
return {
|
|
51571
52579
|
task,
|
|
51572
52580
|
...autoCompleted.length > 0 && { autoCompleted },
|
|
@@ -57502,7 +58510,7 @@ function generateRecommendation2(changeType, affectedCount, cascadeDepth, taskId
|
|
|
57502
58510
|
}
|
|
57503
58511
|
}
|
|
57504
58512
|
function scoreTaskMatch(change, task) {
|
|
57505
|
-
const
|
|
58513
|
+
const STOP_WORDS5 = /* @__PURE__ */ new Set([
|
|
57506
58514
|
"a",
|
|
57507
58515
|
"an",
|
|
57508
58516
|
"the",
|
|
@@ -57524,7 +58532,7 @@ function scoreTaskMatch(change, task) {
|
|
|
57524
58532
|
"do",
|
|
57525
58533
|
"not"
|
|
57526
58534
|
]);
|
|
57527
|
-
const tokenise = (text3) => text3.toLowerCase().split(/\W+/).filter((t) => t.length > 2 && !
|
|
58535
|
+
const tokenise = (text3) => text3.toLowerCase().split(/\W+/).filter((t) => t.length > 2 && !STOP_WORDS5.has(t));
|
|
57528
58536
|
const changeTokens = new Set(tokenise(change));
|
|
57529
58537
|
if (changeTokens.size === 0) return 0;
|
|
57530
58538
|
const taskText = `${task.title ?? ""} ${task.description ?? ""}`;
|
|
@@ -60490,6 +61498,7 @@ __export(memory_exports, {
|
|
|
60490
61498
|
bulkLink: () => bulkLink,
|
|
60491
61499
|
compactManifest: () => compactManifest,
|
|
60492
61500
|
consolidateMemories: () => consolidateMemories,
|
|
61501
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
60493
61502
|
detectContradictions: () => detectContradictions,
|
|
60494
61503
|
ensureFts5Tables: () => ensureFts5Tables,
|
|
60495
61504
|
fetchBrainEntries: () => fetchBrainEntries,
|
|
@@ -60500,6 +61509,7 @@ __export(memory_exports, {
|
|
|
60500
61509
|
getLinkedLearnings: () => getLinkedLearnings,
|
|
60501
61510
|
getLinkedPatterns: () => getLinkedPatterns,
|
|
60502
61511
|
getMemoryLinks: () => getMemoryLinks,
|
|
61512
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
60503
61513
|
getTaskLinks: () => getTaskLinks,
|
|
60504
61514
|
hybridSearch: () => hybridSearch,
|
|
60505
61515
|
learningStats: () => learningStats,
|
|
@@ -60541,6 +61551,7 @@ __export(memory_exports, {
|
|
|
60541
61551
|
storePattern: () => storePattern,
|
|
60542
61552
|
storeVerifiedCandidate: () => storeVerifiedCandidate,
|
|
60543
61553
|
timelineBrain: () => timelineBrain,
|
|
61554
|
+
trackMemoryUsage: () => trackMemoryUsage,
|
|
60544
61555
|
unlinkMemoryFromTask: () => unlinkMemoryFromTask,
|
|
60545
61556
|
updateDecisionOutcome: () => updateDecisionOutcome,
|
|
60546
61557
|
updateResearch: () => updateResearch,
|
|
@@ -60932,6 +61943,7 @@ async function verifyAndStoreBatch(projectRoot, candidates) {
|
|
|
60932
61943
|
// packages/core/src/memory/index.ts
|
|
60933
61944
|
init_learnings();
|
|
60934
61945
|
init_patterns();
|
|
61946
|
+
init_quality_feedback();
|
|
60935
61947
|
function getResearchPath(cwd) {
|
|
60936
61948
|
return join49(getCleoDirAbsolute(cwd), "research.json");
|
|
60937
61949
|
}
|
|
@@ -63848,7 +64860,7 @@ __export(nexus_exports, {
|
|
|
63848
64860
|
criticalPath: () => criticalPath,
|
|
63849
64861
|
discoverRelated: () => discoverRelated,
|
|
63850
64862
|
executeTransfer: () => executeTransfer,
|
|
63851
|
-
extractKeywords: () =>
|
|
64863
|
+
extractKeywords: () => extractKeywords4,
|
|
63852
64864
|
generateProjectHash: () => generateProjectHash,
|
|
63853
64865
|
getCurrentProject: () => getCurrentProject,
|
|
63854
64866
|
getNexusCacheDir: () => getNexusCacheDir,
|
|
@@ -64391,7 +65403,7 @@ async function orphanDetection() {
|
|
|
64391
65403
|
// packages/core/src/nexus/discover.ts
|
|
64392
65404
|
init_data_accessor();
|
|
64393
65405
|
init_registry3();
|
|
64394
|
-
var
|
|
65406
|
+
var STOP_WORDS4 = /* @__PURE__ */ new Set([
|
|
64395
65407
|
"the",
|
|
64396
65408
|
"a",
|
|
64397
65409
|
"an",
|
|
@@ -64473,8 +65485,8 @@ var STOP_WORDS3 = /* @__PURE__ */ new Set([
|
|
|
64473
65485
|
"it",
|
|
64474
65486
|
"its"
|
|
64475
65487
|
]);
|
|
64476
|
-
function
|
|
64477
|
-
return text3.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !
|
|
65488
|
+
function extractKeywords4(text3) {
|
|
65489
|
+
return text3.toLowerCase().replace(/[^a-z0-9\s-]/g, " ").split(/\s+/).filter((w) => w.length > 2 && !STOP_WORDS4.has(w));
|
|
64478
65490
|
}
|
|
64479
65491
|
async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
64480
65492
|
if (!validateSyntax(taskQuery)) {
|
|
@@ -64497,7 +65509,7 @@ async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
|
64497
65509
|
const sourceLabels = new Set(sourceTask.labels ?? []);
|
|
64498
65510
|
const sourceDesc = (sourceTask.description ?? "").toLowerCase();
|
|
64499
65511
|
const sourceTitle = (sourceTask.title ?? "").toLowerCase();
|
|
64500
|
-
const sourceWords =
|
|
65512
|
+
const sourceWords = extractKeywords4(sourceTitle + " " + sourceDesc);
|
|
64501
65513
|
const parsed = parseQuery(taskQuery);
|
|
64502
65514
|
const registry2 = await readRegistry();
|
|
64503
65515
|
if (!registry2) {
|
|
@@ -64532,7 +65544,7 @@ async function discoverRelated(taskQuery, method = "auto", limit = 10) {
|
|
|
64532
65544
|
}
|
|
64533
65545
|
if (method === "description" || method === "auto") {
|
|
64534
65546
|
const taskDesc = ((task.description ?? "") + " " + (task.title ?? "")).toLowerCase();
|
|
64535
|
-
const taskWords =
|
|
65547
|
+
const taskWords = extractKeywords4(taskDesc);
|
|
64536
65548
|
const commonWords = sourceWords.filter((w) => taskWords.includes(w));
|
|
64537
65549
|
if (commonWords.length > 0) {
|
|
64538
65550
|
const descScore = commonWords.length / Math.max(sourceWords.length, taskWords.length, 1);
|
|
@@ -69574,6 +70586,7 @@ __export(research_exports, {
|
|
|
69574
70586
|
bulkLink: () => bulkLink,
|
|
69575
70587
|
compactManifest: () => compactManifest,
|
|
69576
70588
|
consolidateMemories: () => consolidateMemories,
|
|
70589
|
+
correlateOutcomes: () => correlateOutcomes,
|
|
69577
70590
|
detectContradictions: () => detectContradictions,
|
|
69578
70591
|
ensureFts5Tables: () => ensureFts5Tables,
|
|
69579
70592
|
fetchBrainEntries: () => fetchBrainEntries,
|
|
@@ -69584,6 +70597,7 @@ __export(research_exports, {
|
|
|
69584
70597
|
getLinkedLearnings: () => getLinkedLearnings,
|
|
69585
70598
|
getLinkedPatterns: () => getLinkedPatterns,
|
|
69586
70599
|
getMemoryLinks: () => getMemoryLinks,
|
|
70600
|
+
getMemoryQualityReport: () => getMemoryQualityReport,
|
|
69587
70601
|
getTaskLinks: () => getTaskLinks,
|
|
69588
70602
|
hybridSearch: () => hybridSearch,
|
|
69589
70603
|
learningStats: () => learningStats,
|
|
@@ -69625,6 +70639,7 @@ __export(research_exports, {
|
|
|
69625
70639
|
storePattern: () => storePattern,
|
|
69626
70640
|
storeVerifiedCandidate: () => storeVerifiedCandidate,
|
|
69627
70641
|
timelineBrain: () => timelineBrain,
|
|
70642
|
+
trackMemoryUsage: () => trackMemoryUsage,
|
|
69628
70643
|
unlinkMemoryFromTask: () => unlinkMemoryFromTask,
|
|
69629
70644
|
updateDecisionOutcome: () => updateDecisionOutcome,
|
|
69630
70645
|
updateResearch: () => updateResearch,
|