@cleocode/cleo 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.
package/dist/cli/index.js CHANGED
@@ -9071,12 +9071,13 @@ __export(brain_schema_exports, {
9071
9071
  brainPageEdges: () => brainPageEdges,
9072
9072
  brainPageNodes: () => brainPageNodes,
9073
9073
  brainPatterns: () => brainPatterns,
9074
+ brainPlasticityEvents: () => brainPlasticityEvents,
9074
9075
  brainRetrievalLog: () => brainRetrievalLog,
9075
9076
  brainSchemaMeta: () => brainSchemaMeta,
9076
9077
  brainStickyNotes: () => brainStickyNotes
9077
9078
  });
9078
9079
  import { sql as sql2 } from "drizzle-orm";
9079
- 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;
9080
+ 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;
9080
9081
  var init_brain_schema = __esm({
9081
9082
  "packages/core/src/store/brain-schema.ts"() {
9082
9083
  "use strict";
@@ -9505,8 +9506,11 @@ var init_brain_schema = __esm({
9505
9506
  // Graph bridging (memory ↔ code)
9506
9507
  "references",
9507
9508
  // observation → references → symbol
9508
- "modified_by"
9509
+ "modified_by",
9509
9510
  // file → modified_by → session
9511
+ // Plasticity (Hebbian + STDP co-retrieval)
9512
+ "co_retrieved"
9513
+ // A → co_retrieved → B (Hebbian: frequently retrieved together)
9510
9514
  ];
9511
9515
  brainPageNodes = sqliteTable(
9512
9516
  "brain_page_nodes",
@@ -9603,6 +9607,37 @@ var init_brain_schema = __esm({
9603
9607
  index("idx_retrieval_log_source").on(table.source)
9604
9608
  ]
9605
9609
  );
9610
+ brainPlasticityEvents = sqliteTable(
9611
+ "brain_plasticity_events",
9612
+ {
9613
+ id: integer("id").primaryKey({ autoIncrement: true }),
9614
+ /** from_id of the affected brain_page_edges row. */
9615
+ sourceNode: text("source_node").notNull(),
9616
+ /** to_id of the affected brain_page_edges row. */
9617
+ targetNode: text("target_node").notNull(),
9618
+ /**
9619
+ * Signed weight delta applied to the edge.
9620
+ * Positive = potentiation (LTP), negative = depression (LTD).
9621
+ */
9622
+ deltaW: real("delta_w").notNull(),
9623
+ /**
9624
+ * STDP event kind: `ltp` (Long-Term Potentiation) or `ltd` (Long-Term
9625
+ * Depression).
9626
+ */
9627
+ kind: text("kind", { enum: ["ltp", "ltd"] }).notNull(),
9628
+ /** ISO 8601 timestamp when this event was applied. */
9629
+ timestamp: text("timestamp").notNull().default(sql2`(datetime('now'))`),
9630
+ /** Session ID that triggered the STDP pass, if available. */
9631
+ sessionId: text("session_id")
9632
+ },
9633
+ (table) => [
9634
+ index("idx_plasticity_source").on(table.sourceNode),
9635
+ index("idx_plasticity_target").on(table.targetNode),
9636
+ index("idx_plasticity_timestamp").on(table.timestamp),
9637
+ index("idx_plasticity_session").on(table.sessionId),
9638
+ index("idx_plasticity_kind").on(table.kind)
9639
+ ]
9640
+ );
9606
9641
  }
9607
9642
  });
9608
9643
 
@@ -15014,6 +15049,14 @@ function runBrainMigrations(nativeDb, db) {
15014
15049
  );
15015
15050
  }
15016
15051
  ensureColumns(nativeDb, "brain_observations", [{ name: "agent", ddl: "text" }], "brain");
15052
+ if (tableExists(nativeDb, "brain_page_edges")) {
15053
+ nativeDb.prepare(
15054
+ `UPDATE brain_page_edges
15055
+ SET edge_type = 'co_retrieved'
15056
+ WHERE edge_type = 'relates_to'
15057
+ AND provenance LIKE 'consolidation:%'`
15058
+ ).run();
15059
+ }
15017
15060
  }
15018
15061
  function loadBrainVecExtension(nativeDb) {
15019
15062
  try {
@@ -24415,6 +24458,160 @@ var init_anthropic_key_resolver = __esm({
24415
24458
  }
24416
24459
  });
24417
24460
 
24461
+ // packages/core/src/memory/decision-cross-link.ts
24462
+ function extractReferencedSymbols(text3) {
24463
+ const seen = /* @__PURE__ */ new Set();
24464
+ const refs = [];
24465
+ for (const match of text3.matchAll(FILE_PATH_RE)) {
24466
+ const raw = match[1];
24467
+ if (!raw) continue;
24468
+ const nodeId = `file:${raw}`;
24469
+ if (seen.has(nodeId)) continue;
24470
+ seen.add(nodeId);
24471
+ refs.push({ raw, nodeId, nodeType: "file", label: raw });
24472
+ }
24473
+ for (const match of text3.matchAll(SYMBOL_RE)) {
24474
+ const raw = match[0];
24475
+ if (!raw || raw.length < 4) continue;
24476
+ if (SYMBOL_STOP_WORDS.has(raw.toLowerCase())) continue;
24477
+ const nodeId = `symbol:${raw}`;
24478
+ if (seen.has(nodeId)) continue;
24479
+ seen.add(nodeId);
24480
+ refs.push({ raw, nodeId, nodeType: "symbol", label: raw });
24481
+ }
24482
+ return refs;
24483
+ }
24484
+ async function linkDecisionToTargets(projectRoot, decisionId, refs) {
24485
+ const fromId = `decision:${decisionId}`;
24486
+ const writes = refs.map(async (ref) => {
24487
+ await upsertGraphNode(
24488
+ projectRoot,
24489
+ ref.nodeId,
24490
+ ref.nodeType,
24491
+ ref.label,
24492
+ 0.5,
24493
+ // placeholder quality until nexus indexes it
24494
+ ref.raw
24495
+ );
24496
+ await addGraphEdge(
24497
+ projectRoot,
24498
+ fromId,
24499
+ ref.nodeId,
24500
+ "applies_to",
24501
+ 1,
24502
+ "auto:decision-cross-link"
24503
+ );
24504
+ });
24505
+ await Promise.allSettled(writes);
24506
+ }
24507
+ async function autoCrossLinkDecision(projectRoot, decisionId, decisionText, rationale) {
24508
+ try {
24509
+ const combined = `${decisionText} ${rationale}`;
24510
+ const refs = extractReferencedSymbols(combined);
24511
+ if (refs.length === 0) return;
24512
+ await linkDecisionToTargets(projectRoot, decisionId, refs);
24513
+ } catch {
24514
+ }
24515
+ }
24516
+ var FILE_PATH_RE, SYMBOL_RE, SYMBOL_STOP_WORDS;
24517
+ var init_decision_cross_link = __esm({
24518
+ "packages/core/src/memory/decision-cross-link.ts"() {
24519
+ "use strict";
24520
+ init_graph_auto_populate();
24521
+ FILE_PATH_RE = /(?:^|[\s`"'([\]{,])((\/[\w.\-/]+|[\w.-]+(?:\/[\w.-]+)+)\.(ts|tsx|js|jsx|rs|json))(?=$|[\s`"')[\]{,])/gm;
24522
+ 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;
24523
+ SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
24524
+ "this",
24525
+ "that",
24526
+ "with",
24527
+ "from",
24528
+ "into",
24529
+ "when",
24530
+ "then",
24531
+ "also",
24532
+ "both",
24533
+ "each",
24534
+ "such",
24535
+ "over",
24536
+ "after",
24537
+ "before",
24538
+ "always",
24539
+ "never",
24540
+ "should",
24541
+ "must",
24542
+ "will",
24543
+ "would",
24544
+ "could",
24545
+ "have",
24546
+ "been",
24547
+ "there",
24548
+ "their",
24549
+ "they",
24550
+ "them",
24551
+ "these",
24552
+ "those",
24553
+ "some",
24554
+ "only",
24555
+ "just",
24556
+ "more",
24557
+ "most",
24558
+ "many",
24559
+ "much",
24560
+ "well",
24561
+ "very",
24562
+ "here",
24563
+ "where",
24564
+ "which",
24565
+ "what",
24566
+ "why",
24567
+ "how",
24568
+ "the",
24569
+ "and",
24570
+ "but",
24571
+ "for",
24572
+ "not",
24573
+ "are",
24574
+ "was",
24575
+ "were",
24576
+ "has",
24577
+ "had",
24578
+ "its",
24579
+ "the",
24580
+ "data",
24581
+ "true",
24582
+ "false",
24583
+ "null",
24584
+ "none",
24585
+ "type",
24586
+ "test",
24587
+ "spec",
24588
+ "todo",
24589
+ "fixme",
24590
+ "note",
24591
+ "example",
24592
+ "index",
24593
+ "config",
24594
+ "error",
24595
+ "value",
24596
+ "input",
24597
+ "output",
24598
+ "result",
24599
+ "return",
24600
+ "default",
24601
+ "source",
24602
+ "target",
24603
+ "import",
24604
+ "export",
24605
+ "class",
24606
+ "interface",
24607
+ "function",
24608
+ "const",
24609
+ "async",
24610
+ "await"
24611
+ ]);
24612
+ }
24613
+ });
24614
+
24418
24615
  // packages/core/src/memory/decisions.ts
24419
24616
  var decisions_exports = {};
24420
24617
  __export(decisions_exports, {
@@ -24553,6 +24750,8 @@ async function storeDecision(projectRoot, params) {
24553
24750
  "auto:store-decision"
24554
24751
  );
24555
24752
  }
24753
+ autoCrossLinkDecision(projectRoot, saved.id, saved.decision, saved.rationale).catch(() => {
24754
+ });
24556
24755
  } catch {
24557
24756
  }
24558
24757
  detectSupersession(projectRoot, {
@@ -24621,6 +24820,7 @@ var init_decisions2 = __esm({
24621
24820
  init_brain_accessor();
24622
24821
  init_cross_db_cleanup();
24623
24822
  init_sqlite2();
24823
+ init_decision_cross_link();
24624
24824
  init_graph_auto_populate();
24625
24825
  init_quality_scoring();
24626
24826
  init_temporal_supersession();
@@ -45691,6 +45891,30 @@ var init_auto_extract = __esm({
45691
45891
  }
45692
45892
  });
45693
45893
 
45894
+ // packages/core/src/memory/edge-types.ts
45895
+ var EDGE_TYPES;
45896
+ var init_edge_types = __esm({
45897
+ "packages/core/src/memory/edge-types.ts"() {
45898
+ "use strict";
45899
+ EDGE_TYPES = {
45900
+ // Plasticity (Hebbian / STDP co-retrieval)
45901
+ CO_RETRIEVED: "co_retrieved",
45902
+ // Temporal supersession
45903
+ SUPERSEDES: "supersedes",
45904
+ // Task / decision / pattern → target context
45905
+ APPLIES_TO: "applies_to",
45906
+ // Provenance
45907
+ DERIVED_FROM: "derived_from",
45908
+ // Observation → symbol/file impact
45909
+ AFFECTS: "affects",
45910
+ // Observation → symbol name mention
45911
+ MENTIONS: "mentions",
45912
+ // Observation → symbol/file structural link
45913
+ DOCUMENTS: "documents"
45914
+ };
45915
+ }
45916
+ });
45917
+
45694
45918
  // packages/core/src/memory/brain-consolidator.ts
45695
45919
  var brain_consolidator_exports = {};
45696
45920
  __export(brain_consolidator_exports, {
@@ -45924,7 +46148,7 @@ function extractSymbolCandidates(text3) {
45924
46148
  const syms = /* @__PURE__ */ new Set();
45925
46149
  for (const m2 of text3.matchAll(SYMBOL_PATTERN)) {
45926
46150
  const s3 = m2[1];
45927
- if (s3 && s3.length >= 4 && !SYMBOL_STOP_WORDS.has(s3.toLowerCase())) {
46151
+ if (s3 && s3.length >= 4 && !SYMBOL_STOP_WORDS2.has(s3.toLowerCase())) {
45928
46152
  syms.add(s3);
45929
46153
  }
45930
46154
  }
@@ -46233,7 +46457,7 @@ async function listCodeLinks(projectRoot, limit = 100) {
46233
46457
  }
46234
46458
  return entries;
46235
46459
  }
46236
- var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
46460
+ var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS2;
46237
46461
  var init_graph_memory_bridge = __esm({
46238
46462
  "packages/core/src/memory/graph-memory-bridge.ts"() {
46239
46463
  "use strict";
@@ -46243,7 +46467,7 @@ var init_graph_memory_bridge = __esm({
46243
46467
  init_typed_query();
46244
46468
  FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
46245
46469
  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;
46246
- SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
46470
+ SYMBOL_STOP_WORDS2 = /* @__PURE__ */ new Set([
46247
46471
  "true",
46248
46472
  "false",
46249
46473
  "null",
@@ -46287,6 +46511,207 @@ var init_graph_memory_bridge = __esm({
46287
46511
  }
46288
46512
  });
46289
46513
 
46514
+ // packages/core/src/memory/brain-stdp.ts
46515
+ var brain_stdp_exports = {};
46516
+ __export(brain_stdp_exports, {
46517
+ applyStdpPlasticity: () => applyStdpPlasticity,
46518
+ getPlasticityStats: () => getPlasticityStats
46519
+ });
46520
+ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3) {
46521
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
46522
+ await getBrainDb2(projectRoot);
46523
+ const nativeDb = getBrainNativeDb2();
46524
+ const result = {
46525
+ ltpEvents: 0,
46526
+ ltdEvents: 0,
46527
+ edgesCreated: 0,
46528
+ pairsExamined: 0
46529
+ };
46530
+ if (!nativeDb) return result;
46531
+ try {
46532
+ nativeDb.prepare("SELECT 1 FROM brain_retrieval_log LIMIT 1").get();
46533
+ } catch {
46534
+ return result;
46535
+ }
46536
+ try {
46537
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
46538
+ } catch {
46539
+ return result;
46540
+ }
46541
+ const now2 = Date.now();
46542
+ const cutoffMs = now2 - sessionWindowMs;
46543
+ const cutoffIso = new Date(cutoffMs).toISOString().replace("T", " ").slice(0, 19);
46544
+ const nowIso = new Date(now2).toISOString().replace("T", " ").slice(0, 19);
46545
+ let logRows = [];
46546
+ try {
46547
+ logRows = typedAll(
46548
+ nativeDb.prepare(
46549
+ `SELECT id, entry_ids, created_at, retrieval_order, delta_ms
46550
+ FROM brain_retrieval_log
46551
+ WHERE created_at >= ?
46552
+ ORDER BY created_at ASC, id ASC
46553
+ LIMIT 2000`
46554
+ ),
46555
+ cutoffIso
46556
+ );
46557
+ } catch {
46558
+ return result;
46559
+ }
46560
+ if (logRows.length === 0) return result;
46561
+ const spikes = [];
46562
+ let globalOrder = 0;
46563
+ for (const row of logRows) {
46564
+ let ids;
46565
+ try {
46566
+ ids = JSON.parse(row.entry_ids);
46567
+ } catch {
46568
+ continue;
46569
+ }
46570
+ const rowTime = (/* @__PURE__ */ new Date(row.created_at.replace(" ", "T") + "Z")).getTime();
46571
+ for (const rawId of ids) {
46572
+ const entryId = rawId.includes(":") ? rawId : `observation:${rawId}`;
46573
+ spikes.push({
46574
+ entryId,
46575
+ rowId: row.id,
46576
+ retrievedAt: rowTime,
46577
+ order: row.retrieval_order ?? globalOrder
46578
+ });
46579
+ globalOrder++;
46580
+ }
46581
+ }
46582
+ spikes.sort((a, b2) => a.retrievedAt - b2.retrievedAt || a.order - b2.order);
46583
+ const prepareGetEdge = nativeDb.prepare(
46584
+ `SELECT weight FROM brain_page_edges
46585
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
46586
+ );
46587
+ const prepareUpdateEdge = nativeDb.prepare(
46588
+ `UPDATE brain_page_edges
46589
+ SET weight = MAX(?, MIN(?, weight + ?))
46590
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
46591
+ );
46592
+ const prepareInsertEdge = nativeDb.prepare(
46593
+ `INSERT OR IGNORE INTO brain_page_edges
46594
+ (from_id, to_id, edge_type, weight, provenance, created_at)
46595
+ VALUES (?, ?, 'co_retrieved', ?, 'plasticity:stdp-ltp', ?)`
46596
+ );
46597
+ const prepareLogEvent = nativeDb.prepare(
46598
+ `INSERT INTO brain_plasticity_events
46599
+ (source_node, target_node, delta_w, kind, timestamp)
46600
+ VALUES (?, ?, ?, ?, ?)`
46601
+ );
46602
+ for (let i = 0; i < spikes.length; i++) {
46603
+ const spikeA = spikes[i];
46604
+ for (let j2 = i + 1; j2 < spikes.length; j2++) {
46605
+ const spikeB = spikes[j2];
46606
+ const deltaT = spikeB.retrievedAt - spikeA.retrievedAt;
46607
+ if (deltaT > sessionWindowMs) break;
46608
+ if (spikeA.entryId === spikeB.entryId) continue;
46609
+ result.pairsExamined++;
46610
+ const deltaW = A_PRE * Math.exp(-deltaT / TAU_PRE_MS);
46611
+ if (deltaW < 1e-6) continue;
46612
+ const existingEdge = prepareGetEdge.get(spikeA.entryId, spikeB.entryId);
46613
+ try {
46614
+ if (existingEdge !== void 0) {
46615
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaW, spikeA.entryId, spikeB.entryId);
46616
+ } else {
46617
+ const initialWeight = Math.min(WEIGHT_MAX, deltaW);
46618
+ prepareInsertEdge.run(spikeA.entryId, spikeB.entryId, initialWeight, nowIso);
46619
+ result.edgesCreated++;
46620
+ }
46621
+ prepareLogEvent.run(spikeA.entryId, spikeB.entryId, deltaW, "ltp", nowIso);
46622
+ result.ltpEvents++;
46623
+ } catch {
46624
+ }
46625
+ const deltaWNeg = -(A_POST * Math.exp(-deltaT / TAU_POST_MS));
46626
+ const existingReverseEdge = prepareGetEdge.get(spikeB.entryId, spikeA.entryId);
46627
+ if (existingReverseEdge !== void 0 && Math.abs(deltaWNeg) >= 1e-6) {
46628
+ try {
46629
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaWNeg, spikeB.entryId, spikeA.entryId);
46630
+ prepareLogEvent.run(spikeB.entryId, spikeA.entryId, deltaWNeg, "ltd", nowIso);
46631
+ result.ltdEvents++;
46632
+ } catch {
46633
+ }
46634
+ }
46635
+ }
46636
+ }
46637
+ return result;
46638
+ }
46639
+ async function getPlasticityStats(projectRoot, limit = 20) {
46640
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
46641
+ await getBrainDb2(projectRoot);
46642
+ const nativeDb = getBrainNativeDb2();
46643
+ const empty = {
46644
+ totalEvents: 0,
46645
+ ltpCount: 0,
46646
+ ltdCount: 0,
46647
+ netDeltaW: 0,
46648
+ lastEventAt: null,
46649
+ recentEvents: []
46650
+ };
46651
+ if (!nativeDb) return empty;
46652
+ try {
46653
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
46654
+ } catch {
46655
+ return empty;
46656
+ }
46657
+ let agg;
46658
+ try {
46659
+ agg = nativeDb.prepare(
46660
+ `SELECT
46661
+ COUNT(*) AS total,
46662
+ SUM(CASE WHEN kind = 'ltp' THEN 1 ELSE 0 END) AS ltp_count,
46663
+ SUM(CASE WHEN kind = 'ltd' THEN 1 ELSE 0 END) AS ltd_count,
46664
+ SUM(delta_w) AS net_delta_w,
46665
+ MAX(timestamp) AS last_event_at
46666
+ FROM brain_plasticity_events`
46667
+ ).get();
46668
+ } catch {
46669
+ return empty;
46670
+ }
46671
+ let recentRows = [];
46672
+ try {
46673
+ recentRows = typedAll(
46674
+ nativeDb.prepare(
46675
+ `SELECT id, source_node, target_node, delta_w, kind, timestamp, session_id
46676
+ FROM brain_plasticity_events
46677
+ ORDER BY timestamp DESC, id DESC
46678
+ LIMIT ?`
46679
+ ),
46680
+ limit
46681
+ );
46682
+ } catch {
46683
+ }
46684
+ return {
46685
+ totalEvents: agg?.total ?? 0,
46686
+ ltpCount: agg?.ltp_count ?? 0,
46687
+ ltdCount: agg?.ltd_count ?? 0,
46688
+ netDeltaW: agg?.net_delta_w ?? 0,
46689
+ lastEventAt: agg?.last_event_at ?? null,
46690
+ recentEvents: recentRows.map((r) => ({
46691
+ id: r.id,
46692
+ sourceNode: r.source_node,
46693
+ targetNode: r.target_node,
46694
+ deltaW: r.delta_w,
46695
+ kind: r.kind,
46696
+ timestamp: r.timestamp,
46697
+ sessionId: r.session_id
46698
+ }))
46699
+ };
46700
+ }
46701
+ var TAU_PRE_MS, TAU_POST_MS, A_PRE, A_POST, WEIGHT_MIN, WEIGHT_MAX;
46702
+ var init_brain_stdp = __esm({
46703
+ "packages/core/src/memory/brain-stdp.ts"() {
46704
+ "use strict";
46705
+ init_typed_query();
46706
+ TAU_PRE_MS = 2e4;
46707
+ TAU_POST_MS = 2e4;
46708
+ A_PRE = 0.05;
46709
+ A_POST = 0.06;
46710
+ WEIGHT_MIN = 0;
46711
+ WEIGHT_MAX = 1;
46712
+ }
46713
+ });
46714
+
46290
46715
  // packages/core/src/memory/brain-lifecycle.ts
46291
46716
  var brain_lifecycle_exports = {};
46292
46717
  __export(brain_lifecycle_exports, {
@@ -46592,6 +47017,13 @@ async function runConsolidation(projectRoot) {
46592
47017
  } catch (err) {
46593
47018
  console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
46594
47019
  }
47020
+ try {
47021
+ const { applyStdpPlasticity: applyStdpPlasticity2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
47022
+ const stdpResult = await applyStdpPlasticity2(projectRoot);
47023
+ result.stdpPlasticity = stdpResult;
47024
+ } catch (err) {
47025
+ console.warn("[consolidation] Step 9 STDP plasticity failed:", err);
47026
+ }
46595
47027
  return result;
46596
47028
  }
46597
47029
  async function deduplicateByEmbedding(projectRoot) {
@@ -46753,16 +47185,16 @@ async function strengthenCoRetrievedEdges(projectRoot) {
46753
47185
  const updateStmt = nativeDb.prepare(`
46754
47186
  UPDATE brain_page_edges
46755
47187
  SET weight = MIN(1.0, weight + 0.1)
46756
- WHERE from_id = ? AND to_id = ? AND edge_type = 'relates_to'
47188
+ WHERE from_id = ? AND to_id = ? AND edge_type = ?
46757
47189
  `);
46758
- const updateResult = updateStmt.run(nodeFrom, nodeTo);
47190
+ const updateResult = updateStmt.run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED);
46759
47191
  const changes = typeof updateResult.changes === "number" ? updateResult.changes : 0;
46760
47192
  if (changes === 0) {
46761
47193
  nativeDb.prepare(`
46762
47194
  INSERT OR IGNORE INTO brain_page_edges
46763
47195
  (from_id, to_id, edge_type, weight, provenance, created_at)
46764
- VALUES (?, ?, 'relates_to', 0.3, 'consolidation:co-retrieval', ?)
46765
- `).run(nodeFrom, nodeTo, now2);
47196
+ VALUES (?, ?, ?, 0.3, 'consolidation:co-retrieval', ?)
47197
+ `).run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED, now2);
46766
47198
  }
46767
47199
  strengthened++;
46768
47200
  } catch {
@@ -46776,6 +47208,7 @@ var init_brain_lifecycle = __esm({
46776
47208
  "use strict";
46777
47209
  init_brain_accessor();
46778
47210
  init_typed_query();
47211
+ init_edge_types();
46779
47212
  STOP_WORDS3 = /* @__PURE__ */ new Set([
46780
47213
  "the",
46781
47214
  "a",
@@ -60729,6 +61162,7 @@ var init_extraction_gate = __esm({
60729
61162
  // packages/core/src/memory/index.ts
60730
61163
  var memory_exports = {};
60731
61164
  __export(memory_exports, {
61165
+ EDGE_TYPES: () => EDGE_TYPES,
60732
61166
  RRF_K: () => RRF_K,
60733
61167
  addResearch: () => addResearch,
60734
61168
  appendExtendedManifest: () => appendExtendedManifest,
@@ -61412,6 +61846,7 @@ var init_memory = __esm({
61412
61846
  init_brain_retrieval();
61413
61847
  init_brain_search();
61414
61848
  init_decisions2();
61849
+ init_edge_types();
61415
61850
  init_extraction_gate();
61416
61851
  init_learnings();
61417
61852
  init_patterns();
@@ -71602,6 +72037,7 @@ var init_remote = __esm({
71602
72037
  // packages/core/src/research/index.ts
71603
72038
  var research_exports = {};
71604
72039
  __export(research_exports, {
72040
+ EDGE_TYPES: () => EDGE_TYPES,
71605
72041
  RRF_K: () => RRF_K,
71606
72042
  addResearch: () => addResearch,
71607
72043
  appendExtendedManifest: () => appendExtendedManifest,
@@ -112790,6 +113226,7 @@ __export(internal_exports, {
112790
113226
  analyzeDependencies: () => analyzeDependencies2,
112791
113227
  analyzeEpic: () => analyzeEpic,
112792
113228
  analyzeTaskImpact: () => analyzeTaskImpact,
113229
+ applyStdpPlasticity: () => applyStdpPlasticity,
112793
113230
  applyStrictnessPreset: () => applyStrictnessPreset,
112794
113231
  applyTemporalDecay: () => applyTemporalDecay,
112795
113232
  archiveSessions: () => archiveSessions,
@@ -113117,6 +113554,7 @@ __export(internal_exports, {
113117
113554
  getPackageRoot: () => getPackageRoot,
113118
113555
  getParallelStatus: () => getParallelStatus,
113119
113556
  getPipelineStageOrder: () => getPipelineStageOrder,
113557
+ getPlasticityStats: () => getPlasticityStats,
113120
113558
  getProjectAgentRef: () => getProjectAgentRef2,
113121
113559
  getProjectInfo: () => getProjectInfo,
113122
113560
  getProjectInfoSync: () => getProjectInfoSync,
@@ -113583,6 +114021,7 @@ var init_internal = __esm({
113583
114021
  init_brain_maintenance();
113584
114022
  init_brain_purge();
113585
114023
  init_brain_retrieval();
114024
+ init_brain_stdp();
113586
114025
  init_claude_mem_migration();
113587
114026
  init_engine_compat();
113588
114027
  init_pipeline_manifest_sqlite();
@@ -135777,6 +136216,62 @@ function registerBrainCommand(program) {
135777
136216
  process.exit(1);
135778
136217
  }
135779
136218
  });
136219
+ const plasticity = brain.command("plasticity").description("STDP timing-dependent plasticity operations (T626 phase 5)");
136220
+ plasticity.command("stats").description(
136221
+ "Show recent STDP plasticity events: LTP/LTD counts, net weight delta, and most recent events."
136222
+ ).option("--limit <n>", "Maximum recent events to show (default 20)", "20").option("--json", "Output results as JSON").action(async (opts) => {
136223
+ const root = getProjectRoot();
136224
+ const isJson = !!opts.json;
136225
+ const limit = Number(opts.limit ?? "20") || 20;
136226
+ try {
136227
+ const stats2 = await getPlasticityStats(root, limit);
136228
+ if (isJson) {
136229
+ console.log(
136230
+ JSON.stringify(
136231
+ {
136232
+ success: true,
136233
+ data: stats2,
136234
+ meta: { operation: "brain.plasticity.stats", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
136235
+ },
136236
+ null,
136237
+ 2
136238
+ )
136239
+ );
136240
+ return;
136241
+ }
136242
+ console.log("\nBrain Plasticity Stats (STDP)");
136243
+ 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");
136244
+ console.log(` Total events: ${stats2.totalEvents}`);
136245
+ console.log(` LTP (potentiation): ${stats2.ltpCount}`);
136246
+ console.log(` LTD (depression): ${stats2.ltdCount}`);
136247
+ const sign = stats2.netDeltaW >= 0 ? "+" : "";
136248
+ console.log(` Net \u0394w: ${sign}${stats2.netDeltaW.toFixed(4)}`);
136249
+ console.log(` Last event: ${stats2.lastEventAt ?? "(none)"}`);
136250
+ if (stats2.recentEvents.length > 0) {
136251
+ console.log(`
136252
+ Recent Events (newest first, limit=${limit})`);
136253
+ for (const ev of stats2.recentEvents) {
136254
+ const evSign = ev.deltaW >= 0 ? "+" : "";
136255
+ const src = ev.sourceNode.slice(0, 30).padEnd(30);
136256
+ const tgt = ev.targetNode.slice(0, 30).padEnd(30);
136257
+ console.log(
136258
+ ` [${ev.kind.toUpperCase()}] ${src} \u2192 ${tgt} \u0394w=${evSign}${ev.deltaW.toFixed(4)} ${ev.timestamp}`
136259
+ );
136260
+ }
136261
+ } else {
136262
+ console.log("\n No plasticity events recorded yet.");
136263
+ console.log(" Run `cleo brain maintenance` or `cleo session end` to trigger STDP.");
136264
+ }
136265
+ } catch (err) {
136266
+ const message = err instanceof Error ? err.message : String(err);
136267
+ if (isJson) {
136268
+ console.log(JSON.stringify({ success: false, error: message }));
136269
+ } else {
136270
+ console.error(`Brain plasticity stats failed: ${message}`);
136271
+ }
136272
+ process.exit(1);
136273
+ }
136274
+ });
135780
136275
  brain.command("quality").description(
135781
136276
  "Show memory quality metrics: retrieval rates, top/never-retrieved entries, quality distribution, and noise ratio."
135782
136277
  ).option("--json", "Output results as JSON").action(async (opts) => {