@cleocode/core 2026.4.50 → 2026.4.51

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.
Files changed (35) hide show
  1. package/dist/index.js +445 -9
  2. package/dist/index.js.map +4 -4
  3. package/dist/internal.d.ts +2 -0
  4. package/dist/internal.d.ts.map +1 -1
  5. package/dist/internal.js +448 -9
  6. package/dist/internal.js.map +4 -4
  7. package/dist/memory/brain-lifecycle.d.ts +7 -0
  8. package/dist/memory/brain-lifecycle.d.ts.map +1 -1
  9. package/dist/memory/brain-stdp.d.ts +122 -0
  10. package/dist/memory/brain-stdp.d.ts.map +1 -0
  11. package/dist/memory/decision-cross-link.d.ts +70 -0
  12. package/dist/memory/decision-cross-link.d.ts.map +1 -0
  13. package/dist/memory/decisions.d.ts.map +1 -1
  14. package/dist/memory/edge-types.d.ts +24 -0
  15. package/dist/memory/edge-types.d.ts.map +1 -0
  16. package/dist/memory/index.d.ts +1 -0
  17. package/dist/memory/index.d.ts.map +1 -1
  18. package/dist/store/brain-schema.d.ts +134 -3
  19. package/dist/store/brain-schema.d.ts.map +1 -1
  20. package/dist/store/brain-sqlite.d.ts.map +1 -1
  21. package/dist/store/validation-schemas.d.ts +1 -0
  22. package/dist/store/validation-schemas.d.ts.map +1 -1
  23. package/migrations/drizzle-brain/20260415000001_t626-normalize-co-retrieved-edge-type/migration.sql +14 -0
  24. package/package.json +8 -8
  25. package/src/internal.ts +7 -0
  26. package/src/memory/__tests__/brain-stdp.test.ts +452 -0
  27. package/src/memory/__tests__/decision-cross-link.test.ts +240 -0
  28. package/src/memory/brain-lifecycle.ts +23 -4
  29. package/src/memory/brain-stdp.ts +448 -0
  30. package/src/memory/decision-cross-link.ts +276 -0
  31. package/src/memory/decisions.ts +7 -0
  32. package/src/memory/edge-types.ts +31 -0
  33. package/src/memory/index.ts +2 -0
  34. package/src/store/brain-schema.ts +50 -0
  35. package/src/store/brain-sqlite.ts +17 -0
package/dist/index.js CHANGED
@@ -9046,12 +9046,13 @@ __export(brain_schema_exports, {
9046
9046
  brainPageEdges: () => brainPageEdges,
9047
9047
  brainPageNodes: () => brainPageNodes,
9048
9048
  brainPatterns: () => brainPatterns,
9049
+ brainPlasticityEvents: () => brainPlasticityEvents,
9049
9050
  brainRetrievalLog: () => brainRetrievalLog,
9050
9051
  brainSchemaMeta: () => brainSchemaMeta,
9051
9052
  brainStickyNotes: () => brainStickyNotes
9052
9053
  });
9053
9054
  import { sql as sql2 } from "drizzle-orm";
9054
- var BRAIN_MEMORY_TIERS, BRAIN_COGNITIVE_TYPES, BRAIN_SOURCE_CONFIDENCE, BRAIN_DECISION_TYPES, BRAIN_CONFIDENCE_LEVELS, BRAIN_OUTCOME_TYPES, BRAIN_PATTERN_TYPES, BRAIN_IMPACT_LEVELS, BRAIN_LINK_TYPES, BRAIN_OBSERVATION_TYPES2, BRAIN_OBSERVATION_SOURCE_TYPES, BRAIN_MEMORY_TYPES, BRAIN_STICKY_STATUSES, BRAIN_STICKY_COLORS, BRAIN_STICKY_PRIORITIES, brainDecisions, brainPatterns, brainLearnings, brainObservations, brainStickyNotes, brainMemoryLinks, brainSchemaMeta, BRAIN_NODE_TYPES, BRAIN_EDGE_TYPES, brainPageNodes, brainPageEdges, brainRetrievalLog;
9055
+ var BRAIN_MEMORY_TIERS, BRAIN_COGNITIVE_TYPES, BRAIN_SOURCE_CONFIDENCE, BRAIN_DECISION_TYPES, BRAIN_CONFIDENCE_LEVELS, BRAIN_OUTCOME_TYPES, BRAIN_PATTERN_TYPES, BRAIN_IMPACT_LEVELS, BRAIN_LINK_TYPES, BRAIN_OBSERVATION_TYPES2, BRAIN_OBSERVATION_SOURCE_TYPES, BRAIN_MEMORY_TYPES, BRAIN_STICKY_STATUSES, BRAIN_STICKY_COLORS, BRAIN_STICKY_PRIORITIES, brainDecisions, brainPatterns, brainLearnings, brainObservations, brainStickyNotes, brainMemoryLinks, brainSchemaMeta, BRAIN_NODE_TYPES, BRAIN_EDGE_TYPES, brainPageNodes, brainPageEdges, brainRetrievalLog, brainPlasticityEvents;
9055
9056
  var init_brain_schema = __esm({
9056
9057
  "packages/core/src/store/brain-schema.ts"() {
9057
9058
  "use strict";
@@ -9480,8 +9481,11 @@ var init_brain_schema = __esm({
9480
9481
  // Graph bridging (memory ↔ code)
9481
9482
  "references",
9482
9483
  // observation → references → symbol
9483
- "modified_by"
9484
+ "modified_by",
9484
9485
  // file → modified_by → session
9486
+ // Plasticity (Hebbian + STDP co-retrieval)
9487
+ "co_retrieved"
9488
+ // A → co_retrieved → B (Hebbian: frequently retrieved together)
9485
9489
  ];
9486
9490
  brainPageNodes = sqliteTable(
9487
9491
  "brain_page_nodes",
@@ -9578,6 +9582,37 @@ var init_brain_schema = __esm({
9578
9582
  index("idx_retrieval_log_source").on(table.source)
9579
9583
  ]
9580
9584
  );
9585
+ brainPlasticityEvents = sqliteTable(
9586
+ "brain_plasticity_events",
9587
+ {
9588
+ id: integer("id").primaryKey({ autoIncrement: true }),
9589
+ /** from_id of the affected brain_page_edges row. */
9590
+ sourceNode: text("source_node").notNull(),
9591
+ /** to_id of the affected brain_page_edges row. */
9592
+ targetNode: text("target_node").notNull(),
9593
+ /**
9594
+ * Signed weight delta applied to the edge.
9595
+ * Positive = potentiation (LTP), negative = depression (LTD).
9596
+ */
9597
+ deltaW: real("delta_w").notNull(),
9598
+ /**
9599
+ * STDP event kind: `ltp` (Long-Term Potentiation) or `ltd` (Long-Term
9600
+ * Depression).
9601
+ */
9602
+ kind: text("kind", { enum: ["ltp", "ltd"] }).notNull(),
9603
+ /** ISO 8601 timestamp when this event was applied. */
9604
+ timestamp: text("timestamp").notNull().default(sql2`(datetime('now'))`),
9605
+ /** Session ID that triggered the STDP pass, if available. */
9606
+ sessionId: text("session_id")
9607
+ },
9608
+ (table) => [
9609
+ index("idx_plasticity_source").on(table.sourceNode),
9610
+ index("idx_plasticity_target").on(table.targetNode),
9611
+ index("idx_plasticity_timestamp").on(table.timestamp),
9612
+ index("idx_plasticity_session").on(table.sessionId),
9613
+ index("idx_plasticity_kind").on(table.kind)
9614
+ ]
9615
+ );
9581
9616
  }
9582
9617
  });
9583
9618
 
@@ -14444,6 +14479,14 @@ function runBrainMigrations(nativeDb, db) {
14444
14479
  );
14445
14480
  }
14446
14481
  ensureColumns(nativeDb, "brain_observations", [{ name: "agent", ddl: "text" }], "brain");
14482
+ if (tableExists(nativeDb, "brain_page_edges")) {
14483
+ nativeDb.prepare(
14484
+ `UPDATE brain_page_edges
14485
+ SET edge_type = 'co_retrieved'
14486
+ WHERE edge_type = 'relates_to'
14487
+ AND provenance LIKE 'consolidation:%'`
14488
+ ).run();
14489
+ }
14447
14490
  }
14448
14491
  function loadBrainVecExtension(nativeDb) {
14449
14492
  try {
@@ -20956,6 +20999,160 @@ var init_anthropic_key_resolver = __esm({
20956
20999
  }
20957
21000
  });
20958
21001
 
21002
+ // packages/core/src/memory/decision-cross-link.ts
21003
+ function extractReferencedSymbols(text3) {
21004
+ const seen = /* @__PURE__ */ new Set();
21005
+ const refs = [];
21006
+ for (const match of text3.matchAll(FILE_PATH_RE)) {
21007
+ const raw = match[1];
21008
+ if (!raw) continue;
21009
+ const nodeId = `file:${raw}`;
21010
+ if (seen.has(nodeId)) continue;
21011
+ seen.add(nodeId);
21012
+ refs.push({ raw, nodeId, nodeType: "file", label: raw });
21013
+ }
21014
+ for (const match of text3.matchAll(SYMBOL_RE)) {
21015
+ const raw = match[0];
21016
+ if (!raw || raw.length < 4) continue;
21017
+ if (SYMBOL_STOP_WORDS.has(raw.toLowerCase())) continue;
21018
+ const nodeId = `symbol:${raw}`;
21019
+ if (seen.has(nodeId)) continue;
21020
+ seen.add(nodeId);
21021
+ refs.push({ raw, nodeId, nodeType: "symbol", label: raw });
21022
+ }
21023
+ return refs;
21024
+ }
21025
+ async function linkDecisionToTargets(projectRoot, decisionId, refs) {
21026
+ const fromId = `decision:${decisionId}`;
21027
+ const writes = refs.map(async (ref) => {
21028
+ await upsertGraphNode(
21029
+ projectRoot,
21030
+ ref.nodeId,
21031
+ ref.nodeType,
21032
+ ref.label,
21033
+ 0.5,
21034
+ // placeholder quality until nexus indexes it
21035
+ ref.raw
21036
+ );
21037
+ await addGraphEdge(
21038
+ projectRoot,
21039
+ fromId,
21040
+ ref.nodeId,
21041
+ "applies_to",
21042
+ 1,
21043
+ "auto:decision-cross-link"
21044
+ );
21045
+ });
21046
+ await Promise.allSettled(writes);
21047
+ }
21048
+ async function autoCrossLinkDecision(projectRoot, decisionId, decisionText, rationale) {
21049
+ try {
21050
+ const combined = `${decisionText} ${rationale}`;
21051
+ const refs = extractReferencedSymbols(combined);
21052
+ if (refs.length === 0) return;
21053
+ await linkDecisionToTargets(projectRoot, decisionId, refs);
21054
+ } catch {
21055
+ }
21056
+ }
21057
+ var FILE_PATH_RE, SYMBOL_RE, SYMBOL_STOP_WORDS;
21058
+ var init_decision_cross_link = __esm({
21059
+ "packages/core/src/memory/decision-cross-link.ts"() {
21060
+ "use strict";
21061
+ init_graph_auto_populate();
21062
+ FILE_PATH_RE = /(?:^|[\s`"'([\]{,])((\/[\w.\-/]+|[\w.-]+(?:\/[\w.-]+)+)\.(ts|tsx|js|jsx|rs|json))(?=$|[\s`"')[\]{,])/gm;
21063
+ SYMBOL_RE = /(?<![`"'/\w.])(?:[A-Z][a-zA-Z0-9]{2,}|[a-z][a-zA-Z0-9]*(?:[A-Z][a-zA-Z0-9]*)+|[a-z][a-z0-9]*(?:_[a-z][a-z0-9]*){2,})(?![`"'/\w])/g;
21064
+ SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
21065
+ "this",
21066
+ "that",
21067
+ "with",
21068
+ "from",
21069
+ "into",
21070
+ "when",
21071
+ "then",
21072
+ "also",
21073
+ "both",
21074
+ "each",
21075
+ "such",
21076
+ "over",
21077
+ "after",
21078
+ "before",
21079
+ "always",
21080
+ "never",
21081
+ "should",
21082
+ "must",
21083
+ "will",
21084
+ "would",
21085
+ "could",
21086
+ "have",
21087
+ "been",
21088
+ "there",
21089
+ "their",
21090
+ "they",
21091
+ "them",
21092
+ "these",
21093
+ "those",
21094
+ "some",
21095
+ "only",
21096
+ "just",
21097
+ "more",
21098
+ "most",
21099
+ "many",
21100
+ "much",
21101
+ "well",
21102
+ "very",
21103
+ "here",
21104
+ "where",
21105
+ "which",
21106
+ "what",
21107
+ "why",
21108
+ "how",
21109
+ "the",
21110
+ "and",
21111
+ "but",
21112
+ "for",
21113
+ "not",
21114
+ "are",
21115
+ "was",
21116
+ "were",
21117
+ "has",
21118
+ "had",
21119
+ "its",
21120
+ "the",
21121
+ "data",
21122
+ "true",
21123
+ "false",
21124
+ "null",
21125
+ "none",
21126
+ "type",
21127
+ "test",
21128
+ "spec",
21129
+ "todo",
21130
+ "fixme",
21131
+ "note",
21132
+ "example",
21133
+ "index",
21134
+ "config",
21135
+ "error",
21136
+ "value",
21137
+ "input",
21138
+ "output",
21139
+ "result",
21140
+ "return",
21141
+ "default",
21142
+ "source",
21143
+ "target",
21144
+ "import",
21145
+ "export",
21146
+ "class",
21147
+ "interface",
21148
+ "function",
21149
+ "const",
21150
+ "async",
21151
+ "await"
21152
+ ]);
21153
+ }
21154
+ });
21155
+
20959
21156
  // packages/core/src/memory/decisions.ts
20960
21157
  var decisions_exports = {};
20961
21158
  __export(decisions_exports, {
@@ -21094,6 +21291,8 @@ async function storeDecision(projectRoot, params) {
21094
21291
  "auto:store-decision"
21095
21292
  );
21096
21293
  }
21294
+ autoCrossLinkDecision(projectRoot, saved.id, saved.decision, saved.rationale).catch(() => {
21295
+ });
21097
21296
  } catch {
21098
21297
  }
21099
21298
  detectSupersession(projectRoot, {
@@ -21162,6 +21361,7 @@ var init_decisions2 = __esm({
21162
21361
  init_brain_accessor();
21163
21362
  init_cross_db_cleanup();
21164
21363
  init_sqlite2();
21364
+ init_decision_cross_link();
21165
21365
  init_graph_auto_populate();
21166
21366
  init_quality_scoring();
21167
21367
  init_temporal_supersession();
@@ -42232,6 +42432,30 @@ var init_auto_extract = __esm({
42232
42432
  }
42233
42433
  });
42234
42434
 
42435
+ // packages/core/src/memory/edge-types.ts
42436
+ var EDGE_TYPES;
42437
+ var init_edge_types = __esm({
42438
+ "packages/core/src/memory/edge-types.ts"() {
42439
+ "use strict";
42440
+ EDGE_TYPES = {
42441
+ // Plasticity (Hebbian / STDP co-retrieval)
42442
+ CO_RETRIEVED: "co_retrieved",
42443
+ // Temporal supersession
42444
+ SUPERSEDES: "supersedes",
42445
+ // Task / decision / pattern → target context
42446
+ APPLIES_TO: "applies_to",
42447
+ // Provenance
42448
+ DERIVED_FROM: "derived_from",
42449
+ // Observation → symbol/file impact
42450
+ AFFECTS: "affects",
42451
+ // Observation → symbol name mention
42452
+ MENTIONS: "mentions",
42453
+ // Observation → symbol/file structural link
42454
+ DOCUMENTS: "documents"
42455
+ };
42456
+ }
42457
+ });
42458
+
42235
42459
  // packages/core/src/memory/brain-consolidator.ts
42236
42460
  var brain_consolidator_exports = {};
42237
42461
  __export(brain_consolidator_exports, {
@@ -42465,7 +42689,7 @@ function extractSymbolCandidates(text3) {
42465
42689
  const syms = /* @__PURE__ */ new Set();
42466
42690
  for (const m of text3.matchAll(SYMBOL_PATTERN)) {
42467
42691
  const s = m[1];
42468
- if (s && s.length >= 4 && !SYMBOL_STOP_WORDS.has(s.toLowerCase())) {
42692
+ if (s && s.length >= 4 && !SYMBOL_STOP_WORDS2.has(s.toLowerCase())) {
42469
42693
  syms.add(s);
42470
42694
  }
42471
42695
  }
@@ -42774,7 +42998,7 @@ async function listCodeLinks(projectRoot, limit = 100) {
42774
42998
  }
42775
42999
  return entries;
42776
43000
  }
42777
- var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
43001
+ var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS2;
42778
43002
  var init_graph_memory_bridge = __esm({
42779
43003
  "packages/core/src/memory/graph-memory-bridge.ts"() {
42780
43004
  "use strict";
@@ -42784,7 +43008,7 @@ var init_graph_memory_bridge = __esm({
42784
43008
  init_typed_query();
42785
43009
  FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
42786
43010
  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;
42787
- SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
43011
+ SYMBOL_STOP_WORDS2 = /* @__PURE__ */ new Set([
42788
43012
  "true",
42789
43013
  "false",
42790
43014
  "null",
@@ -42828,6 +43052,207 @@ var init_graph_memory_bridge = __esm({
42828
43052
  }
42829
43053
  });
42830
43054
 
43055
+ // packages/core/src/memory/brain-stdp.ts
43056
+ var brain_stdp_exports = {};
43057
+ __export(brain_stdp_exports, {
43058
+ applyStdpPlasticity: () => applyStdpPlasticity,
43059
+ getPlasticityStats: () => getPlasticityStats
43060
+ });
43061
+ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3) {
43062
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
43063
+ await getBrainDb2(projectRoot);
43064
+ const nativeDb = getBrainNativeDb2();
43065
+ const result = {
43066
+ ltpEvents: 0,
43067
+ ltdEvents: 0,
43068
+ edgesCreated: 0,
43069
+ pairsExamined: 0
43070
+ };
43071
+ if (!nativeDb) return result;
43072
+ try {
43073
+ nativeDb.prepare("SELECT 1 FROM brain_retrieval_log LIMIT 1").get();
43074
+ } catch {
43075
+ return result;
43076
+ }
43077
+ try {
43078
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
43079
+ } catch {
43080
+ return result;
43081
+ }
43082
+ const now = Date.now();
43083
+ const cutoffMs = now - sessionWindowMs;
43084
+ const cutoffIso = new Date(cutoffMs).toISOString().replace("T", " ").slice(0, 19);
43085
+ const nowIso = new Date(now).toISOString().replace("T", " ").slice(0, 19);
43086
+ let logRows = [];
43087
+ try {
43088
+ logRows = typedAll(
43089
+ nativeDb.prepare(
43090
+ `SELECT id, entry_ids, created_at, retrieval_order, delta_ms
43091
+ FROM brain_retrieval_log
43092
+ WHERE created_at >= ?
43093
+ ORDER BY created_at ASC, id ASC
43094
+ LIMIT 2000`
43095
+ ),
43096
+ cutoffIso
43097
+ );
43098
+ } catch {
43099
+ return result;
43100
+ }
43101
+ if (logRows.length === 0) return result;
43102
+ const spikes = [];
43103
+ let globalOrder = 0;
43104
+ for (const row of logRows) {
43105
+ let ids;
43106
+ try {
43107
+ ids = JSON.parse(row.entry_ids);
43108
+ } catch {
43109
+ continue;
43110
+ }
43111
+ const rowTime = (/* @__PURE__ */ new Date(row.created_at.replace(" ", "T") + "Z")).getTime();
43112
+ for (const rawId of ids) {
43113
+ const entryId = rawId.includes(":") ? rawId : `observation:${rawId}`;
43114
+ spikes.push({
43115
+ entryId,
43116
+ rowId: row.id,
43117
+ retrievedAt: rowTime,
43118
+ order: row.retrieval_order ?? globalOrder
43119
+ });
43120
+ globalOrder++;
43121
+ }
43122
+ }
43123
+ spikes.sort((a, b) => a.retrievedAt - b.retrievedAt || a.order - b.order);
43124
+ const prepareGetEdge = nativeDb.prepare(
43125
+ `SELECT weight FROM brain_page_edges
43126
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
43127
+ );
43128
+ const prepareUpdateEdge = nativeDb.prepare(
43129
+ `UPDATE brain_page_edges
43130
+ SET weight = MAX(?, MIN(?, weight + ?))
43131
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
43132
+ );
43133
+ const prepareInsertEdge = nativeDb.prepare(
43134
+ `INSERT OR IGNORE INTO brain_page_edges
43135
+ (from_id, to_id, edge_type, weight, provenance, created_at)
43136
+ VALUES (?, ?, 'co_retrieved', ?, 'plasticity:stdp-ltp', ?)`
43137
+ );
43138
+ const prepareLogEvent = nativeDb.prepare(
43139
+ `INSERT INTO brain_plasticity_events
43140
+ (source_node, target_node, delta_w, kind, timestamp)
43141
+ VALUES (?, ?, ?, ?, ?)`
43142
+ );
43143
+ for (let i = 0; i < spikes.length; i++) {
43144
+ const spikeA = spikes[i];
43145
+ for (let j = i + 1; j < spikes.length; j++) {
43146
+ const spikeB = spikes[j];
43147
+ const deltaT = spikeB.retrievedAt - spikeA.retrievedAt;
43148
+ if (deltaT > sessionWindowMs) break;
43149
+ if (spikeA.entryId === spikeB.entryId) continue;
43150
+ result.pairsExamined++;
43151
+ const deltaW = A_PRE * Math.exp(-deltaT / TAU_PRE_MS);
43152
+ if (deltaW < 1e-6) continue;
43153
+ const existingEdge = prepareGetEdge.get(spikeA.entryId, spikeB.entryId);
43154
+ try {
43155
+ if (existingEdge !== void 0) {
43156
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaW, spikeA.entryId, spikeB.entryId);
43157
+ } else {
43158
+ const initialWeight = Math.min(WEIGHT_MAX, deltaW);
43159
+ prepareInsertEdge.run(spikeA.entryId, spikeB.entryId, initialWeight, nowIso);
43160
+ result.edgesCreated++;
43161
+ }
43162
+ prepareLogEvent.run(spikeA.entryId, spikeB.entryId, deltaW, "ltp", nowIso);
43163
+ result.ltpEvents++;
43164
+ } catch {
43165
+ }
43166
+ const deltaWNeg = -(A_POST * Math.exp(-deltaT / TAU_POST_MS));
43167
+ const existingReverseEdge = prepareGetEdge.get(spikeB.entryId, spikeA.entryId);
43168
+ if (existingReverseEdge !== void 0 && Math.abs(deltaWNeg) >= 1e-6) {
43169
+ try {
43170
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaWNeg, spikeB.entryId, spikeA.entryId);
43171
+ prepareLogEvent.run(spikeB.entryId, spikeA.entryId, deltaWNeg, "ltd", nowIso);
43172
+ result.ltdEvents++;
43173
+ } catch {
43174
+ }
43175
+ }
43176
+ }
43177
+ }
43178
+ return result;
43179
+ }
43180
+ async function getPlasticityStats(projectRoot, limit = 20) {
43181
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
43182
+ await getBrainDb2(projectRoot);
43183
+ const nativeDb = getBrainNativeDb2();
43184
+ const empty = {
43185
+ totalEvents: 0,
43186
+ ltpCount: 0,
43187
+ ltdCount: 0,
43188
+ netDeltaW: 0,
43189
+ lastEventAt: null,
43190
+ recentEvents: []
43191
+ };
43192
+ if (!nativeDb) return empty;
43193
+ try {
43194
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
43195
+ } catch {
43196
+ return empty;
43197
+ }
43198
+ let agg;
43199
+ try {
43200
+ agg = nativeDb.prepare(
43201
+ `SELECT
43202
+ COUNT(*) AS total,
43203
+ SUM(CASE WHEN kind = 'ltp' THEN 1 ELSE 0 END) AS ltp_count,
43204
+ SUM(CASE WHEN kind = 'ltd' THEN 1 ELSE 0 END) AS ltd_count,
43205
+ SUM(delta_w) AS net_delta_w,
43206
+ MAX(timestamp) AS last_event_at
43207
+ FROM brain_plasticity_events`
43208
+ ).get();
43209
+ } catch {
43210
+ return empty;
43211
+ }
43212
+ let recentRows = [];
43213
+ try {
43214
+ recentRows = typedAll(
43215
+ nativeDb.prepare(
43216
+ `SELECT id, source_node, target_node, delta_w, kind, timestamp, session_id
43217
+ FROM brain_plasticity_events
43218
+ ORDER BY timestamp DESC, id DESC
43219
+ LIMIT ?`
43220
+ ),
43221
+ limit
43222
+ );
43223
+ } catch {
43224
+ }
43225
+ return {
43226
+ totalEvents: agg?.total ?? 0,
43227
+ ltpCount: agg?.ltp_count ?? 0,
43228
+ ltdCount: agg?.ltd_count ?? 0,
43229
+ netDeltaW: agg?.net_delta_w ?? 0,
43230
+ lastEventAt: agg?.last_event_at ?? null,
43231
+ recentEvents: recentRows.map((r) => ({
43232
+ id: r.id,
43233
+ sourceNode: r.source_node,
43234
+ targetNode: r.target_node,
43235
+ deltaW: r.delta_w,
43236
+ kind: r.kind,
43237
+ timestamp: r.timestamp,
43238
+ sessionId: r.session_id
43239
+ }))
43240
+ };
43241
+ }
43242
+ var TAU_PRE_MS, TAU_POST_MS, A_PRE, A_POST, WEIGHT_MIN, WEIGHT_MAX;
43243
+ var init_brain_stdp = __esm({
43244
+ "packages/core/src/memory/brain-stdp.ts"() {
43245
+ "use strict";
43246
+ init_typed_query();
43247
+ TAU_PRE_MS = 2e4;
43248
+ TAU_POST_MS = 2e4;
43249
+ A_PRE = 0.05;
43250
+ A_POST = 0.06;
43251
+ WEIGHT_MIN = 0;
43252
+ WEIGHT_MAX = 1;
43253
+ }
43254
+ });
43255
+
42831
43256
  // packages/core/src/memory/brain-lifecycle.ts
42832
43257
  var brain_lifecycle_exports = {};
42833
43258
  __export(brain_lifecycle_exports, {
@@ -43133,6 +43558,13 @@ async function runConsolidation(projectRoot) {
43133
43558
  } catch (err) {
43134
43559
  console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
43135
43560
  }
43561
+ try {
43562
+ const { applyStdpPlasticity: applyStdpPlasticity2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
43563
+ const stdpResult = await applyStdpPlasticity2(projectRoot);
43564
+ result.stdpPlasticity = stdpResult;
43565
+ } catch (err) {
43566
+ console.warn("[consolidation] Step 9 STDP plasticity failed:", err);
43567
+ }
43136
43568
  return result;
43137
43569
  }
43138
43570
  async function deduplicateByEmbedding(projectRoot) {
@@ -43294,16 +43726,16 @@ async function strengthenCoRetrievedEdges(projectRoot) {
43294
43726
  const updateStmt = nativeDb.prepare(`
43295
43727
  UPDATE brain_page_edges
43296
43728
  SET weight = MIN(1.0, weight + 0.1)
43297
- WHERE from_id = ? AND to_id = ? AND edge_type = 'relates_to'
43729
+ WHERE from_id = ? AND to_id = ? AND edge_type = ?
43298
43730
  `);
43299
- const updateResult = updateStmt.run(nodeFrom, nodeTo);
43731
+ const updateResult = updateStmt.run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED);
43300
43732
  const changes = typeof updateResult.changes === "number" ? updateResult.changes : 0;
43301
43733
  if (changes === 0) {
43302
43734
  nativeDb.prepare(`
43303
43735
  INSERT OR IGNORE INTO brain_page_edges
43304
43736
  (from_id, to_id, edge_type, weight, provenance, created_at)
43305
- VALUES (?, ?, 'relates_to', 0.3, 'consolidation:co-retrieval', ?)
43306
- `).run(nodeFrom, nodeTo, now);
43737
+ VALUES (?, ?, ?, 0.3, 'consolidation:co-retrieval', ?)
43738
+ `).run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED, now);
43307
43739
  }
43308
43740
  strengthened++;
43309
43741
  } catch {
@@ -43317,6 +43749,7 @@ var init_brain_lifecycle = __esm({
43317
43749
  "use strict";
43318
43750
  init_brain_accessor();
43319
43751
  init_typed_query();
43752
+ init_edge_types();
43320
43753
  STOP_WORDS3 = /* @__PURE__ */ new Set([
43321
43754
  "the",
43322
43755
  "a",
@@ -61645,6 +62078,7 @@ async function listEpicsWithLifecycle(cwd) {
61645
62078
  // packages/core/src/memory/index.ts
61646
62079
  var memory_exports = {};
61647
62080
  __export(memory_exports, {
62081
+ EDGE_TYPES: () => EDGE_TYPES,
61648
62082
  RRF_K: () => RRF_K,
61649
62083
  addResearch: () => addResearch,
61650
62084
  appendExtendedManifest: () => appendExtendedManifest,
@@ -61842,6 +62276,7 @@ function mapImpact(impact) {
61842
62276
  init_brain_retrieval();
61843
62277
  init_brain_search();
61844
62278
  init_decisions2();
62279
+ init_edge_types();
61845
62280
 
61846
62281
  // packages/core/src/memory/extraction-gate.ts
61847
62282
  init_brain_embedding();
@@ -70734,6 +71169,7 @@ async function getSyncStatus(remote = "origin", cwd) {
70734
71169
  // packages/core/src/research/index.ts
70735
71170
  var research_exports = {};
70736
71171
  __export(research_exports, {
71172
+ EDGE_TYPES: () => EDGE_TYPES,
70737
71173
  RRF_K: () => RRF_K,
70738
71174
  addResearch: () => addResearch,
70739
71175
  appendExtendedManifest: () => appendExtendedManifest,