@cleocode/core 2026.4.50 → 2026.4.52

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 (52) hide show
  1. package/dist/index.js +511 -41
  2. package/dist/index.js.map +4 -4
  3. package/dist/internal.d.ts +4 -0
  4. package/dist/internal.d.ts.map +1 -1
  5. package/dist/internal.js +669 -45
  6. package/dist/internal.js.map +4 -4
  7. package/dist/memory/brain-export.d.ts +70 -0
  8. package/dist/memory/brain-export.d.ts.map +1 -0
  9. package/dist/memory/brain-lifecycle.d.ts +7 -0
  10. package/dist/memory/brain-lifecycle.d.ts.map +1 -1
  11. package/dist/memory/brain-retrieval.d.ts.map +1 -1
  12. package/dist/memory/brain-stdp.d.ts +122 -0
  13. package/dist/memory/brain-stdp.d.ts.map +1 -0
  14. package/dist/memory/decision-cross-link.d.ts +70 -0
  15. package/dist/memory/decision-cross-link.d.ts.map +1 -0
  16. package/dist/memory/decisions.d.ts.map +1 -1
  17. package/dist/memory/edge-types.d.ts +24 -0
  18. package/dist/memory/edge-types.d.ts.map +1 -0
  19. package/dist/memory/index.d.ts +1 -0
  20. package/dist/memory/index.d.ts.map +1 -1
  21. package/dist/store/brain-schema.d.ts +150 -3
  22. package/dist/store/brain-schema.d.ts.map +1 -1
  23. package/dist/store/brain-sqlite.d.ts.map +1 -1
  24. package/dist/store/validation-schemas.d.ts +1 -0
  25. package/dist/store/validation-schemas.d.ts.map +1 -1
  26. package/dist/validation/verification.d.ts.map +1 -1
  27. package/migrations/drizzle-brain/20260415000001_t626-normalize-co-retrieved-edge-type/migration.sql +14 -0
  28. package/package.json +8 -8
  29. package/src/internal.ts +14 -0
  30. package/src/memory/__tests__/brain-stdp.test.ts +452 -0
  31. package/src/memory/__tests__/decision-cross-link.test.ts +240 -0
  32. package/src/memory/brain-embedding.ts +1 -1
  33. package/src/memory/brain-export.ts +286 -0
  34. package/src/memory/brain-lifecycle.ts +23 -4
  35. package/src/memory/brain-retrieval.ts +80 -14
  36. package/src/memory/brain-similarity.ts +1 -1
  37. package/src/memory/brain-stdp.ts +448 -0
  38. package/src/memory/claude-mem-migration.ts +1 -1
  39. package/src/memory/decision-cross-link.ts +276 -0
  40. package/src/memory/decisions.ts +7 -0
  41. package/src/memory/edge-types.ts +31 -0
  42. package/src/memory/index.ts +2 -0
  43. package/src/sessions/briefing.ts +1 -1
  44. package/src/skills/dispatch.ts +1 -1
  45. package/src/skills/injection/subagent.ts +1 -1
  46. package/src/skills/orchestrator/spawn.ts +1 -1
  47. package/src/store/brain-schema.ts +54 -0
  48. package/src/store/brain-sqlite.ts +17 -0
  49. package/src/store/json.ts +2 -2
  50. package/src/system/archive-analytics.ts +1 -1
  51. package/src/tasks/task-ops.ts +2 -2
  52. package/src/validation/verification.ts +2 -6
package/dist/internal.js CHANGED
@@ -9069,12 +9069,13 @@ __export(brain_schema_exports, {
9069
9069
  brainPageEdges: () => brainPageEdges,
9070
9070
  brainPageNodes: () => brainPageNodes,
9071
9071
  brainPatterns: () => brainPatterns,
9072
+ brainPlasticityEvents: () => brainPlasticityEvents,
9072
9073
  brainRetrievalLog: () => brainRetrievalLog,
9073
9074
  brainSchemaMeta: () => brainSchemaMeta,
9074
9075
  brainStickyNotes: () => brainStickyNotes
9075
9076
  });
9076
9077
  import { sql as sql2 } from "drizzle-orm";
9077
- 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;
9078
+ 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;
9078
9079
  var init_brain_schema = __esm({
9079
9080
  "packages/core/src/store/brain-schema.ts"() {
9080
9081
  "use strict";
@@ -9503,8 +9504,11 @@ var init_brain_schema = __esm({
9503
9504
  // Graph bridging (memory ↔ code)
9504
9505
  "references",
9505
9506
  // observation → references → symbol
9506
- "modified_by"
9507
+ "modified_by",
9507
9508
  // file → modified_by → session
9509
+ // Plasticity (Hebbian + STDP co-retrieval)
9510
+ "co_retrieved"
9511
+ // A → co_retrieved → B (Hebbian: frequently retrieved together)
9508
9512
  ];
9509
9513
  brainPageNodes = sqliteTable(
9510
9514
  "brain_page_nodes",
@@ -9594,11 +9598,45 @@ var init_brain_schema = __esm({
9594
9598
  source: text("source").notNull(),
9595
9599
  /** Estimated tokens consumed by this retrieval. */
9596
9600
  tokensUsed: integer("tokens_used"),
9601
+ /** Session ID (soft FK to tasks.db sessions). Enables grouping retrievals by session for STDP analysis. */
9602
+ sessionId: text("session_id"),
9597
9603
  createdAt: text("created_at").notNull().default(sql2`(datetime('now'))`)
9598
9604
  },
9599
9605
  (table) => [
9600
9606
  index("idx_retrieval_log_created").on(table.createdAt),
9601
- index("idx_retrieval_log_source").on(table.source)
9607
+ index("idx_retrieval_log_source").on(table.source),
9608
+ index("idx_retrieval_log_session").on(table.sessionId)
9609
+ ]
9610
+ );
9611
+ brainPlasticityEvents = sqliteTable(
9612
+ "brain_plasticity_events",
9613
+ {
9614
+ id: integer("id").primaryKey({ autoIncrement: true }),
9615
+ /** from_id of the affected brain_page_edges row. */
9616
+ sourceNode: text("source_node").notNull(),
9617
+ /** to_id of the affected brain_page_edges row. */
9618
+ targetNode: text("target_node").notNull(),
9619
+ /**
9620
+ * Signed weight delta applied to the edge.
9621
+ * Positive = potentiation (LTP), negative = depression (LTD).
9622
+ */
9623
+ deltaW: real("delta_w").notNull(),
9624
+ /**
9625
+ * STDP event kind: `ltp` (Long-Term Potentiation) or `ltd` (Long-Term
9626
+ * Depression).
9627
+ */
9628
+ kind: text("kind", { enum: ["ltp", "ltd"] }).notNull(),
9629
+ /** ISO 8601 timestamp when this event was applied. */
9630
+ timestamp: text("timestamp").notNull().default(sql2`(datetime('now'))`),
9631
+ /** Session ID that triggered the STDP pass, if available. */
9632
+ sessionId: text("session_id")
9633
+ },
9634
+ (table) => [
9635
+ index("idx_plasticity_source").on(table.sourceNode),
9636
+ index("idx_plasticity_target").on(table.targetNode),
9637
+ index("idx_plasticity_timestamp").on(table.timestamp),
9638
+ index("idx_plasticity_session").on(table.sessionId),
9639
+ index("idx_plasticity_kind").on(table.kind)
9602
9640
  ]
9603
9641
  );
9604
9642
  }
@@ -14915,7 +14953,7 @@ function clearEmbeddingProvider() {
14915
14953
  currentProvider = null;
14916
14954
  }
14917
14955
  async function embedText(text3) {
14918
- if (!currentProvider || !currentProvider.isAvailable()) return null;
14956
+ if (!currentProvider?.isAvailable()) return null;
14919
14957
  return currentProvider.embed(text3);
14920
14958
  }
14921
14959
  function isEmbeddingAvailable() {
@@ -15012,6 +15050,14 @@ function runBrainMigrations(nativeDb, db) {
15012
15050
  );
15013
15051
  }
15014
15052
  ensureColumns(nativeDb, "brain_observations", [{ name: "agent", ddl: "text" }], "brain");
15053
+ if (tableExists(nativeDb, "brain_page_edges")) {
15054
+ nativeDb.prepare(
15055
+ `UPDATE brain_page_edges
15056
+ SET edge_type = 'co_retrieved'
15057
+ WHERE edge_type = 'relates_to'
15058
+ AND provenance LIKE 'consolidation:%'`
15059
+ ).run();
15060
+ }
15015
15061
  }
15016
15062
  function loadBrainVecExtension(nativeDb) {
15017
15063
  try {
@@ -20057,7 +20103,7 @@ function parseIdPrefix(id) {
20057
20103
  return null;
20058
20104
  }
20059
20105
  async function searchSimilar(query, projectRoot, limit) {
20060
- if (!query || !query.trim()) return [];
20106
+ if (!query?.trim()) return [];
20061
20107
  if (!isEmbeddingAvailable()) return [];
20062
20108
  const maxResults = limit ?? 10;
20063
20109
  const queryVector = await embedText(query);
@@ -21692,6 +21738,160 @@ var init_anthropic_key_resolver = __esm({
21692
21738
  }
21693
21739
  });
21694
21740
 
21741
+ // packages/core/src/memory/decision-cross-link.ts
21742
+ function extractReferencedSymbols(text3) {
21743
+ const seen = /* @__PURE__ */ new Set();
21744
+ const refs = [];
21745
+ for (const match of text3.matchAll(FILE_PATH_RE)) {
21746
+ const raw = match[1];
21747
+ if (!raw) continue;
21748
+ const nodeId = `file:${raw}`;
21749
+ if (seen.has(nodeId)) continue;
21750
+ seen.add(nodeId);
21751
+ refs.push({ raw, nodeId, nodeType: "file", label: raw });
21752
+ }
21753
+ for (const match of text3.matchAll(SYMBOL_RE)) {
21754
+ const raw = match[0];
21755
+ if (!raw || raw.length < 4) continue;
21756
+ if (SYMBOL_STOP_WORDS.has(raw.toLowerCase())) continue;
21757
+ const nodeId = `symbol:${raw}`;
21758
+ if (seen.has(nodeId)) continue;
21759
+ seen.add(nodeId);
21760
+ refs.push({ raw, nodeId, nodeType: "symbol", label: raw });
21761
+ }
21762
+ return refs;
21763
+ }
21764
+ async function linkDecisionToTargets(projectRoot, decisionId, refs) {
21765
+ const fromId = `decision:${decisionId}`;
21766
+ const writes = refs.map(async (ref) => {
21767
+ await upsertGraphNode(
21768
+ projectRoot,
21769
+ ref.nodeId,
21770
+ ref.nodeType,
21771
+ ref.label,
21772
+ 0.5,
21773
+ // placeholder quality until nexus indexes it
21774
+ ref.raw
21775
+ );
21776
+ await addGraphEdge(
21777
+ projectRoot,
21778
+ fromId,
21779
+ ref.nodeId,
21780
+ "applies_to",
21781
+ 1,
21782
+ "auto:decision-cross-link"
21783
+ );
21784
+ });
21785
+ await Promise.allSettled(writes);
21786
+ }
21787
+ async function autoCrossLinkDecision(projectRoot, decisionId, decisionText, rationale) {
21788
+ try {
21789
+ const combined = `${decisionText} ${rationale}`;
21790
+ const refs = extractReferencedSymbols(combined);
21791
+ if (refs.length === 0) return;
21792
+ await linkDecisionToTargets(projectRoot, decisionId, refs);
21793
+ } catch {
21794
+ }
21795
+ }
21796
+ var FILE_PATH_RE, SYMBOL_RE, SYMBOL_STOP_WORDS;
21797
+ var init_decision_cross_link = __esm({
21798
+ "packages/core/src/memory/decision-cross-link.ts"() {
21799
+ "use strict";
21800
+ init_graph_auto_populate();
21801
+ FILE_PATH_RE = /(?:^|[\s`"'([\]{,])((\/[\w.\-/]+|[\w.-]+(?:\/[\w.-]+)+)\.(ts|tsx|js|jsx|rs|json))(?=$|[\s`"')[\]{,])/gm;
21802
+ 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;
21803
+ SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
21804
+ "this",
21805
+ "that",
21806
+ "with",
21807
+ "from",
21808
+ "into",
21809
+ "when",
21810
+ "then",
21811
+ "also",
21812
+ "both",
21813
+ "each",
21814
+ "such",
21815
+ "over",
21816
+ "after",
21817
+ "before",
21818
+ "always",
21819
+ "never",
21820
+ "should",
21821
+ "must",
21822
+ "will",
21823
+ "would",
21824
+ "could",
21825
+ "have",
21826
+ "been",
21827
+ "there",
21828
+ "their",
21829
+ "they",
21830
+ "them",
21831
+ "these",
21832
+ "those",
21833
+ "some",
21834
+ "only",
21835
+ "just",
21836
+ "more",
21837
+ "most",
21838
+ "many",
21839
+ "much",
21840
+ "well",
21841
+ "very",
21842
+ "here",
21843
+ "where",
21844
+ "which",
21845
+ "what",
21846
+ "why",
21847
+ "how",
21848
+ "the",
21849
+ "and",
21850
+ "but",
21851
+ "for",
21852
+ "not",
21853
+ "are",
21854
+ "was",
21855
+ "were",
21856
+ "has",
21857
+ "had",
21858
+ "its",
21859
+ "the",
21860
+ "data",
21861
+ "true",
21862
+ "false",
21863
+ "null",
21864
+ "none",
21865
+ "type",
21866
+ "test",
21867
+ "spec",
21868
+ "todo",
21869
+ "fixme",
21870
+ "note",
21871
+ "example",
21872
+ "index",
21873
+ "config",
21874
+ "error",
21875
+ "value",
21876
+ "input",
21877
+ "output",
21878
+ "result",
21879
+ "return",
21880
+ "default",
21881
+ "source",
21882
+ "target",
21883
+ "import",
21884
+ "export",
21885
+ "class",
21886
+ "interface",
21887
+ "function",
21888
+ "const",
21889
+ "async",
21890
+ "await"
21891
+ ]);
21892
+ }
21893
+ });
21894
+
21695
21895
  // packages/core/src/memory/decisions.ts
21696
21896
  var decisions_exports = {};
21697
21897
  __export(decisions_exports, {
@@ -21830,6 +22030,8 @@ async function storeDecision(projectRoot, params) {
21830
22030
  "auto:store-decision"
21831
22031
  );
21832
22032
  }
22033
+ autoCrossLinkDecision(projectRoot, saved.id, saved.decision, saved.rationale).catch(() => {
22034
+ });
21833
22035
  } catch {
21834
22036
  }
21835
22037
  detectSupersession(projectRoot, {
@@ -21898,6 +22100,7 @@ var init_decisions2 = __esm({
21898
22100
  init_brain_accessor();
21899
22101
  init_cross_db_cleanup();
21900
22102
  init_sqlite2();
22103
+ init_decision_cross_link();
21901
22104
  init_graph_auto_populate();
21902
22105
  init_quality_scoring();
21903
22106
  init_temporal_supersession();
@@ -42968,6 +43171,30 @@ var init_auto_extract = __esm({
42968
43171
  }
42969
43172
  });
42970
43173
 
43174
+ // packages/core/src/memory/edge-types.ts
43175
+ var EDGE_TYPES;
43176
+ var init_edge_types = __esm({
43177
+ "packages/core/src/memory/edge-types.ts"() {
43178
+ "use strict";
43179
+ EDGE_TYPES = {
43180
+ // Plasticity (Hebbian / STDP co-retrieval)
43181
+ CO_RETRIEVED: "co_retrieved",
43182
+ // Temporal supersession
43183
+ SUPERSEDES: "supersedes",
43184
+ // Task / decision / pattern → target context
43185
+ APPLIES_TO: "applies_to",
43186
+ // Provenance
43187
+ DERIVED_FROM: "derived_from",
43188
+ // Observation → symbol/file impact
43189
+ AFFECTS: "affects",
43190
+ // Observation → symbol name mention
43191
+ MENTIONS: "mentions",
43192
+ // Observation → symbol/file structural link
43193
+ DOCUMENTS: "documents"
43194
+ };
43195
+ }
43196
+ });
43197
+
42971
43198
  // packages/core/src/memory/brain-consolidator.ts
42972
43199
  var brain_consolidator_exports = {};
42973
43200
  __export(brain_consolidator_exports, {
@@ -43201,7 +43428,7 @@ function extractSymbolCandidates(text3) {
43201
43428
  const syms = /* @__PURE__ */ new Set();
43202
43429
  for (const m2 of text3.matchAll(SYMBOL_PATTERN)) {
43203
43430
  const s3 = m2[1];
43204
- if (s3 && s3.length >= 4 && !SYMBOL_STOP_WORDS.has(s3.toLowerCase())) {
43431
+ if (s3 && s3.length >= 4 && !SYMBOL_STOP_WORDS2.has(s3.toLowerCase())) {
43205
43432
  syms.add(s3);
43206
43433
  }
43207
43434
  }
@@ -43510,7 +43737,7 @@ async function listCodeLinks(projectRoot, limit = 100) {
43510
43737
  }
43511
43738
  return entries;
43512
43739
  }
43513
- var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS;
43740
+ var FILE_PATH_PATTERN, SYMBOL_PATTERN, SYMBOL_STOP_WORDS2;
43514
43741
  var init_graph_memory_bridge = __esm({
43515
43742
  "packages/core/src/memory/graph-memory-bridge.ts"() {
43516
43743
  "use strict";
@@ -43520,7 +43747,7 @@ var init_graph_memory_bridge = __esm({
43520
43747
  init_typed_query();
43521
43748
  FILE_PATH_PATTERN = /(?:^|\s|['"`(])([a-zA-Z0-9_\-./]+\.(?:ts|tsx|js|jsx|rs|go|py|mjs|cjs))(?:$|\s|['"`)])/g;
43522
43749
  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;
43523
- SYMBOL_STOP_WORDS = /* @__PURE__ */ new Set([
43750
+ SYMBOL_STOP_WORDS2 = /* @__PURE__ */ new Set([
43524
43751
  "true",
43525
43752
  "false",
43526
43753
  "null",
@@ -43564,6 +43791,207 @@ var init_graph_memory_bridge = __esm({
43564
43791
  }
43565
43792
  });
43566
43793
 
43794
+ // packages/core/src/memory/brain-stdp.ts
43795
+ var brain_stdp_exports = {};
43796
+ __export(brain_stdp_exports, {
43797
+ applyStdpPlasticity: () => applyStdpPlasticity,
43798
+ getPlasticityStats: () => getPlasticityStats
43799
+ });
43800
+ async function applyStdpPlasticity(projectRoot, sessionWindowMs = 5 * 60 * 1e3) {
43801
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
43802
+ await getBrainDb2(projectRoot);
43803
+ const nativeDb = getBrainNativeDb2();
43804
+ const result = {
43805
+ ltpEvents: 0,
43806
+ ltdEvents: 0,
43807
+ edgesCreated: 0,
43808
+ pairsExamined: 0
43809
+ };
43810
+ if (!nativeDb) return result;
43811
+ try {
43812
+ nativeDb.prepare("SELECT 1 FROM brain_retrieval_log LIMIT 1").get();
43813
+ } catch {
43814
+ return result;
43815
+ }
43816
+ try {
43817
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
43818
+ } catch {
43819
+ return result;
43820
+ }
43821
+ const now2 = Date.now();
43822
+ const cutoffMs = now2 - sessionWindowMs;
43823
+ const cutoffIso = new Date(cutoffMs).toISOString().replace("T", " ").slice(0, 19);
43824
+ const nowIso = new Date(now2).toISOString().replace("T", " ").slice(0, 19);
43825
+ let logRows = [];
43826
+ try {
43827
+ logRows = typedAll(
43828
+ nativeDb.prepare(
43829
+ `SELECT id, entry_ids, created_at, retrieval_order, delta_ms
43830
+ FROM brain_retrieval_log
43831
+ WHERE created_at >= ?
43832
+ ORDER BY created_at ASC, id ASC
43833
+ LIMIT 2000`
43834
+ ),
43835
+ cutoffIso
43836
+ );
43837
+ } catch {
43838
+ return result;
43839
+ }
43840
+ if (logRows.length === 0) return result;
43841
+ const spikes = [];
43842
+ let globalOrder = 0;
43843
+ for (const row of logRows) {
43844
+ let ids;
43845
+ try {
43846
+ ids = JSON.parse(row.entry_ids);
43847
+ } catch {
43848
+ continue;
43849
+ }
43850
+ const rowTime = (/* @__PURE__ */ new Date(row.created_at.replace(" ", "T") + "Z")).getTime();
43851
+ for (const rawId of ids) {
43852
+ const entryId = rawId.includes(":") ? rawId : `observation:${rawId}`;
43853
+ spikes.push({
43854
+ entryId,
43855
+ rowId: row.id,
43856
+ retrievedAt: rowTime,
43857
+ order: row.retrieval_order ?? globalOrder
43858
+ });
43859
+ globalOrder++;
43860
+ }
43861
+ }
43862
+ spikes.sort((a, b2) => a.retrievedAt - b2.retrievedAt || a.order - b2.order);
43863
+ const prepareGetEdge = nativeDb.prepare(
43864
+ `SELECT weight FROM brain_page_edges
43865
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
43866
+ );
43867
+ const prepareUpdateEdge = nativeDb.prepare(
43868
+ `UPDATE brain_page_edges
43869
+ SET weight = MAX(?, MIN(?, weight + ?))
43870
+ WHERE from_id = ? AND to_id = ? AND edge_type = 'co_retrieved'`
43871
+ );
43872
+ const prepareInsertEdge = nativeDb.prepare(
43873
+ `INSERT OR IGNORE INTO brain_page_edges
43874
+ (from_id, to_id, edge_type, weight, provenance, created_at)
43875
+ VALUES (?, ?, 'co_retrieved', ?, 'plasticity:stdp-ltp', ?)`
43876
+ );
43877
+ const prepareLogEvent = nativeDb.prepare(
43878
+ `INSERT INTO brain_plasticity_events
43879
+ (source_node, target_node, delta_w, kind, timestamp)
43880
+ VALUES (?, ?, ?, ?, ?)`
43881
+ );
43882
+ for (let i = 0; i < spikes.length; i++) {
43883
+ const spikeA = spikes[i];
43884
+ for (let j2 = i + 1; j2 < spikes.length; j2++) {
43885
+ const spikeB = spikes[j2];
43886
+ const deltaT = spikeB.retrievedAt - spikeA.retrievedAt;
43887
+ if (deltaT > sessionWindowMs) break;
43888
+ if (spikeA.entryId === spikeB.entryId) continue;
43889
+ result.pairsExamined++;
43890
+ const deltaW = A_PRE * Math.exp(-deltaT / TAU_PRE_MS);
43891
+ if (deltaW < 1e-6) continue;
43892
+ const existingEdge = prepareGetEdge.get(spikeA.entryId, spikeB.entryId);
43893
+ try {
43894
+ if (existingEdge !== void 0) {
43895
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaW, spikeA.entryId, spikeB.entryId);
43896
+ } else {
43897
+ const initialWeight = Math.min(WEIGHT_MAX, deltaW);
43898
+ prepareInsertEdge.run(spikeA.entryId, spikeB.entryId, initialWeight, nowIso);
43899
+ result.edgesCreated++;
43900
+ }
43901
+ prepareLogEvent.run(spikeA.entryId, spikeB.entryId, deltaW, "ltp", nowIso);
43902
+ result.ltpEvents++;
43903
+ } catch {
43904
+ }
43905
+ const deltaWNeg = -(A_POST * Math.exp(-deltaT / TAU_POST_MS));
43906
+ const existingReverseEdge = prepareGetEdge.get(spikeB.entryId, spikeA.entryId);
43907
+ if (existingReverseEdge !== void 0 && Math.abs(deltaWNeg) >= 1e-6) {
43908
+ try {
43909
+ prepareUpdateEdge.run(WEIGHT_MIN, WEIGHT_MAX, deltaWNeg, spikeB.entryId, spikeA.entryId);
43910
+ prepareLogEvent.run(spikeB.entryId, spikeA.entryId, deltaWNeg, "ltd", nowIso);
43911
+ result.ltdEvents++;
43912
+ } catch {
43913
+ }
43914
+ }
43915
+ }
43916
+ }
43917
+ return result;
43918
+ }
43919
+ async function getPlasticityStats(projectRoot, limit = 20) {
43920
+ const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
43921
+ await getBrainDb2(projectRoot);
43922
+ const nativeDb = getBrainNativeDb2();
43923
+ const empty = {
43924
+ totalEvents: 0,
43925
+ ltpCount: 0,
43926
+ ltdCount: 0,
43927
+ netDeltaW: 0,
43928
+ lastEventAt: null,
43929
+ recentEvents: []
43930
+ };
43931
+ if (!nativeDb) return empty;
43932
+ try {
43933
+ nativeDb.prepare("SELECT 1 FROM brain_plasticity_events LIMIT 1").get();
43934
+ } catch {
43935
+ return empty;
43936
+ }
43937
+ let agg;
43938
+ try {
43939
+ agg = nativeDb.prepare(
43940
+ `SELECT
43941
+ COUNT(*) AS total,
43942
+ SUM(CASE WHEN kind = 'ltp' THEN 1 ELSE 0 END) AS ltp_count,
43943
+ SUM(CASE WHEN kind = 'ltd' THEN 1 ELSE 0 END) AS ltd_count,
43944
+ SUM(delta_w) AS net_delta_w,
43945
+ MAX(timestamp) AS last_event_at
43946
+ FROM brain_plasticity_events`
43947
+ ).get();
43948
+ } catch {
43949
+ return empty;
43950
+ }
43951
+ let recentRows = [];
43952
+ try {
43953
+ recentRows = typedAll(
43954
+ nativeDb.prepare(
43955
+ `SELECT id, source_node, target_node, delta_w, kind, timestamp, session_id
43956
+ FROM brain_plasticity_events
43957
+ ORDER BY timestamp DESC, id DESC
43958
+ LIMIT ?`
43959
+ ),
43960
+ limit
43961
+ );
43962
+ } catch {
43963
+ }
43964
+ return {
43965
+ totalEvents: agg?.total ?? 0,
43966
+ ltpCount: agg?.ltp_count ?? 0,
43967
+ ltdCount: agg?.ltd_count ?? 0,
43968
+ netDeltaW: agg?.net_delta_w ?? 0,
43969
+ lastEventAt: agg?.last_event_at ?? null,
43970
+ recentEvents: recentRows.map((r) => ({
43971
+ id: r.id,
43972
+ sourceNode: r.source_node,
43973
+ targetNode: r.target_node,
43974
+ deltaW: r.delta_w,
43975
+ kind: r.kind,
43976
+ timestamp: r.timestamp,
43977
+ sessionId: r.session_id
43978
+ }))
43979
+ };
43980
+ }
43981
+ var TAU_PRE_MS, TAU_POST_MS, A_PRE, A_POST, WEIGHT_MIN, WEIGHT_MAX;
43982
+ var init_brain_stdp = __esm({
43983
+ "packages/core/src/memory/brain-stdp.ts"() {
43984
+ "use strict";
43985
+ init_typed_query();
43986
+ TAU_PRE_MS = 2e4;
43987
+ TAU_POST_MS = 2e4;
43988
+ A_PRE = 0.05;
43989
+ A_POST = 0.06;
43990
+ WEIGHT_MIN = 0;
43991
+ WEIGHT_MAX = 1;
43992
+ }
43993
+ });
43994
+
43567
43995
  // packages/core/src/memory/brain-lifecycle.ts
43568
43996
  var brain_lifecycle_exports = {};
43569
43997
  __export(brain_lifecycle_exports, {
@@ -43869,6 +44297,13 @@ async function runConsolidation(projectRoot) {
43869
44297
  } catch (err) {
43870
44298
  console.warn("[consolidation] Step 8 graph memory bridge failed:", err);
43871
44299
  }
44300
+ try {
44301
+ const { applyStdpPlasticity: applyStdpPlasticity2 } = await Promise.resolve().then(() => (init_brain_stdp(), brain_stdp_exports));
44302
+ const stdpResult = await applyStdpPlasticity2(projectRoot);
44303
+ result.stdpPlasticity = stdpResult;
44304
+ } catch (err) {
44305
+ console.warn("[consolidation] Step 9 STDP plasticity failed:", err);
44306
+ }
43872
44307
  return result;
43873
44308
  }
43874
44309
  async function deduplicateByEmbedding(projectRoot) {
@@ -44030,16 +44465,16 @@ async function strengthenCoRetrievedEdges(projectRoot) {
44030
44465
  const updateStmt = nativeDb.prepare(`
44031
44466
  UPDATE brain_page_edges
44032
44467
  SET weight = MIN(1.0, weight + 0.1)
44033
- WHERE from_id = ? AND to_id = ? AND edge_type = 'relates_to'
44468
+ WHERE from_id = ? AND to_id = ? AND edge_type = ?
44034
44469
  `);
44035
- const updateResult = updateStmt.run(nodeFrom, nodeTo);
44470
+ const updateResult = updateStmt.run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED);
44036
44471
  const changes = typeof updateResult.changes === "number" ? updateResult.changes : 0;
44037
44472
  if (changes === 0) {
44038
44473
  nativeDb.prepare(`
44039
44474
  INSERT OR IGNORE INTO brain_page_edges
44040
44475
  (from_id, to_id, edge_type, weight, provenance, created_at)
44041
- VALUES (?, ?, 'relates_to', 0.3, 'consolidation:co-retrieval', ?)
44042
- `).run(nodeFrom, nodeTo, now2);
44476
+ VALUES (?, ?, ?, 0.3, 'consolidation:co-retrieval', ?)
44477
+ `).run(nodeFrom, nodeTo, EDGE_TYPES.CO_RETRIEVED, now2);
44043
44478
  }
44044
44479
  strengthened++;
44045
44480
  } catch {
@@ -44053,6 +44488,7 @@ var init_brain_lifecycle = __esm({
44053
44488
  "use strict";
44054
44489
  init_brain_accessor();
44055
44490
  init_typed_query();
44491
+ init_edge_types();
44056
44492
  STOP_WORDS3 = /* @__PURE__ */ new Set([
44057
44493
  "the",
44058
44494
  "a",
@@ -47214,7 +47650,7 @@ async function computeLastSession(projectRoot, scopeFilter) {
47214
47650
  const accessor = await getAccessor(projectRoot);
47215
47651
  const allSessions = await accessor.loadSessions();
47216
47652
  const session = allSessions.find((s3) => s3.id === sessionId);
47217
- if (!session || !session.endedAt) return null;
47653
+ if (!session?.endedAt) return null;
47218
47654
  let duration3 = 0;
47219
47655
  if (session.startedAt) {
47220
47656
  duration3 = Math.round(
@@ -48401,10 +48837,17 @@ async function searchBrainCompact(projectRoot, params) {
48401
48837
  setImmediate(() => {
48402
48838
  incrementCitationCounts(projectRoot, returnedIds).catch(() => {
48403
48839
  });
48404
- logRetrieval(projectRoot, query, returnedIds, "find-rrf", results2.length * 50).catch(
48405
- () => {
48406
- }
48407
- );
48840
+ getCurrentSessionId(projectRoot).then((sessionId) => {
48841
+ return logRetrieval(
48842
+ projectRoot,
48843
+ query,
48844
+ returnedIds,
48845
+ "find-rrf",
48846
+ results2.length * 50,
48847
+ sessionId
48848
+ );
48849
+ }).catch(() => {
48850
+ });
48408
48851
  });
48409
48852
  }
48410
48853
  return { results: results2, total: results2.length, tokensEstimated: results2.length * 50 };
@@ -48467,7 +48910,16 @@ async function searchBrainCompact(projectRoot, params) {
48467
48910
  setImmediate(() => {
48468
48911
  incrementCitationCounts(projectRoot, returnedIds).catch(() => {
48469
48912
  });
48470
- logRetrieval(projectRoot, query, returnedIds, "find", results.length * 50).catch(() => {
48913
+ getCurrentSessionId(projectRoot).then((sessionId) => {
48914
+ return logRetrieval(
48915
+ projectRoot,
48916
+ query,
48917
+ returnedIds,
48918
+ "find",
48919
+ results.length * 50,
48920
+ sessionId
48921
+ );
48922
+ }).catch(() => {
48471
48923
  });
48472
48924
  });
48473
48925
  }
@@ -48655,13 +49107,16 @@ async function fetchBrainEntries(projectRoot, params) {
48655
49107
  setImmediate(() => {
48656
49108
  incrementCitationCounts(projectRoot, fetchedIds).catch(() => {
48657
49109
  });
48658
- logRetrieval(
48659
- projectRoot,
48660
- fetchedIds.join(","),
48661
- fetchedIds,
48662
- "fetch",
48663
- results.length * 500
48664
- ).catch(() => {
49110
+ getCurrentSessionId(projectRoot).then((sessionId) => {
49111
+ return logRetrieval(
49112
+ projectRoot,
49113
+ fetchedIds.join(","),
49114
+ fetchedIds,
49115
+ "fetch",
49116
+ results.length * 500,
49117
+ sessionId
49118
+ );
49119
+ }).catch(() => {
48665
49120
  });
48666
49121
  });
48667
49122
  }
@@ -49079,6 +49534,15 @@ async function retrieveWithBudget(projectRoot, query, tokenBudget = 500, options
49079
49534
  excluded
49080
49535
  };
49081
49536
  }
49537
+ async function getCurrentSessionId(projectRoot) {
49538
+ try {
49539
+ const { sessionStatus: sessionStatus2 } = await Promise.resolve().then(() => (init_sessions2(), sessions_exports2));
49540
+ const session = await sessionStatus2(projectRoot);
49541
+ return session?.id;
49542
+ } catch {
49543
+ return void 0;
49544
+ }
49545
+ }
49082
49546
  async function incrementCitationCounts(projectRoot, ids) {
49083
49547
  if (ids.length === 0) return;
49084
49548
  const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
@@ -49105,13 +49569,13 @@ async function incrementCitationCounts(projectRoot, ids) {
49105
49569
  }
49106
49570
  }
49107
49571
  }
49108
- async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
49572
+ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed, sessionId) {
49109
49573
  if (entryIds.length === 0) return;
49110
49574
  const { getBrainDb: getBrainDb2, getBrainNativeDb: getBrainNativeDb2 } = await Promise.resolve().then(() => (init_brain_sqlite(), brain_sqlite_exports));
49111
49575
  await getBrainDb2(projectRoot);
49112
49576
  const nativeDb = getBrainNativeDb2();
49113
49577
  if (!nativeDb) return;
49114
- const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
49578
+ const createSql = "CREATE TABLE IF NOT EXISTS brain_retrieval_log (id INTEGER PRIMARY KEY AUTOINCREMENT,query TEXT NOT NULL,entry_ids TEXT NOT NULL,entry_count INTEGER NOT NULL,source TEXT NOT NULL,tokens_used INTEGER,session_id TEXT,created_at TEXT NOT NULL DEFAULT (datetime('now')))";
49115
49579
  try {
49116
49580
  nativeDb.prepare(createSql).run();
49117
49581
  } catch {
@@ -49119,8 +49583,15 @@ async function logRetrieval(projectRoot, query, entryIds, source, tokensUsed) {
49119
49583
  }
49120
49584
  try {
49121
49585
  nativeDb.prepare(
49122
- "INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used) VALUES (?, ?, ?, ?, ?)"
49123
- ).run(query, entryIds.join(","), entryIds.length, source, tokensUsed ?? null);
49586
+ "INSERT INTO brain_retrieval_log (query, entry_ids, entry_count, source, tokens_used, session_id) VALUES (?, ?, ?, ?, ?, ?)"
49587
+ ).run(
49588
+ query,
49589
+ entryIds.join(","),
49590
+ entryIds.length,
49591
+ source,
49592
+ tokensUsed ?? null,
49593
+ sessionId ?? null
49594
+ );
49124
49595
  } catch {
49125
49596
  }
49126
49597
  }
@@ -72404,7 +72875,7 @@ function prepareSpawnMulti(skillNames, tokenValues, cwd) {
72404
72875
  const skillName = skillNames[i];
72405
72876
  const isPrimary = i === 0;
72406
72877
  const skill = findSkill(skillName, cwd);
72407
- if (!skill || !skill.content) {
72878
+ if (!skill?.content) {
72408
72879
  continue;
72409
72880
  }
72410
72881
  let content = isPrimary ? skill.content : loadProgressive(skill.content);
@@ -73091,6 +73562,7 @@ async function listEpicsWithLifecycle(cwd) {
73091
73562
  // packages/core/src/memory/index.ts
73092
73563
  var memory_exports = {};
73093
73564
  __export(memory_exports, {
73565
+ EDGE_TYPES: () => EDGE_TYPES,
73094
73566
  RRF_K: () => RRF_K,
73095
73567
  addResearch: () => addResearch,
73096
73568
  appendExtendedManifest: () => appendExtendedManifest,
@@ -73288,6 +73760,7 @@ function mapImpact(impact) {
73288
73760
  init_brain_retrieval();
73289
73761
  init_brain_search();
73290
73762
  init_decisions2();
73763
+ init_edge_types();
73291
73764
 
73292
73765
  // packages/core/src/memory/extraction-gate.ts
73293
73766
  init_brain_embedding();
@@ -81673,6 +82146,7 @@ async function getSyncStatus(remote = "origin", cwd) {
81673
82146
  // packages/core/src/research/index.ts
81674
82147
  var research_exports = {};
81675
82148
  __export(research_exports, {
82149
+ EDGE_TYPES: () => EDGE_TYPES,
81676
82150
  RRF_K: () => RRF_K,
81677
82151
  addResearch: () => addResearch,
81678
82152
  appendExtendedManifest: () => appendExtendedManifest,
@@ -84063,7 +84537,7 @@ async function injectProtocol(skillContent, taskId, tokenValues, cwd, tier) {
84063
84537
  }
84064
84538
  async function orchestratorSpawnSkill(taskId, skillName, tokenValues, cwd, tier) {
84065
84539
  const skill = findSkill(skillName, cwd);
84066
- if (!skill || !skill.content) {
84540
+ if (!skill?.content) {
84067
84541
  throw new CleoError(4 /* NOT_FOUND */, `Skill not found: ${skillName}`, {
84068
84542
  fix: `Check skills directory for ${skillName}/SKILL.md`
84069
84543
  });
@@ -84599,7 +85073,7 @@ async function buildPrompt(taskId, templateName = "TASK-EXECUTOR", cwd, tier) {
84599
85073
  throw new CleoError(4 /* NOT_FOUND */, `Task ${taskId} not found`);
84600
85074
  }
84601
85075
  const skill = findSkill(templateName, cwd);
84602
- if (!skill || !skill.content) {
85076
+ if (!skill?.content) {
84603
85077
  const { canonical } = mapSkillName(templateName);
84604
85078
  throw new CleoError(4 /* NOT_FOUND */, `Skill template ${templateName} not found`, {
84605
85079
  fix: `Expected at skills/${canonical}/SKILL.md`
@@ -87099,7 +87573,7 @@ async function analyzeArchive(opts, accessor) {
87099
87573
  const acc = accessor ?? await getAccessor(opts.cwd);
87100
87574
  const data = await acc.loadArchive();
87101
87575
  const reportType = opts.report ?? "summary";
87102
- if (!data || !data.archivedTasks?.length) {
87576
+ if (!data?.archivedTasks?.length) {
87103
87577
  return {
87104
87578
  report: reportType,
87105
87579
  filters: null,
@@ -93030,16 +93504,12 @@ function allEpicChildrenVerified(epicId, tasks2) {
93030
93504
  if (children.length === 0) return false;
93031
93505
  const incomplete = children.filter((t) => t.status !== "done");
93032
93506
  if (incomplete.length > 0) return false;
93033
- const unverified = children.filter(
93034
- (t) => t.status === "done" && (!t.verification || !t.verification.passed)
93035
- );
93507
+ const unverified = children.filter((t) => t.status === "done" && !t.verification?.passed);
93036
93508
  return unverified.length === 0;
93037
93509
  }
93038
93510
  function allSiblingsVerified(parentId, tasks2) {
93039
93511
  const siblings = tasks2.filter((t) => t.parentId === parentId);
93040
- const unverifiedDone = siblings.filter(
93041
- (t) => t.status === "done" && (!t.verification || !t.verification.passed)
93042
- );
93512
+ const unverifiedDone = siblings.filter((t) => t.status === "done" && !t.verification?.passed);
93043
93513
  const incomplete = siblings.filter(
93044
93514
  (t) => t.status === "pending" || t.status === "active" || t.status === "blocked"
93045
93515
  );
@@ -93417,7 +93887,7 @@ import { randomUUID as randomUUID8 } from "node:crypto";
93417
93887
  init_paths();
93418
93888
  import { existsSync as existsSync109, readFileSync as readFileSync77, writeFileSync as writeFileSync20 } from "node:fs";
93419
93889
  import { join as join108 } from "node:path";
93420
- function getCurrentSessionId(cwd) {
93890
+ function getCurrentSessionId2(cwd) {
93421
93891
  if (process.env.CLEO_SESSION) return process.env.CLEO_SESSION;
93422
93892
  const sessionFile = join108(getCleoDir(cwd), ".current-session");
93423
93893
  if (existsSync109(sessionFile)) {
@@ -93445,7 +93915,7 @@ function createCliMeta(operation, duration_ms = 0) {
93445
93915
  duration_ms,
93446
93916
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
93447
93917
  };
93448
- const sessionId = getCurrentSessionId();
93918
+ const sessionId = getCurrentSessionId2();
93449
93919
  if (sessionId) {
93450
93920
  meta3["sessionId"] = sessionId;
93451
93921
  }
@@ -96947,6 +97417,155 @@ async function backfillBrainGraph(projectRoot) {
96947
97417
  };
96948
97418
  }
96949
97419
 
97420
+ // packages/core/src/memory/brain-export.ts
97421
+ init_brain_schema();
97422
+ init_brain_sqlite();
97423
+ async function exportBrainAsGexf(projectRoot) {
97424
+ const db = await getBrainDb(projectRoot);
97425
+ let nodes = [];
97426
+ let edges = [];
97427
+ try {
97428
+ nodes = await db.select({
97429
+ id: brainPageNodes.id,
97430
+ nodeType: brainPageNodes.nodeType,
97431
+ label: brainPageNodes.label,
97432
+ qualityScore: brainPageNodes.qualityScore,
97433
+ contentHash: brainPageNodes.contentHash,
97434
+ lastActivityAt: brainPageNodes.lastActivityAt,
97435
+ metadataJson: brainPageNodes.metadataJson,
97436
+ createdAt: brainPageNodes.createdAt,
97437
+ updatedAt: brainPageNodes.updatedAt
97438
+ }).from(brainPageNodes);
97439
+ } catch {
97440
+ nodes = [];
97441
+ }
97442
+ try {
97443
+ const rawEdges = await db.select({
97444
+ fromId: brainPageEdges.fromId,
97445
+ toId: brainPageEdges.toId,
97446
+ edgeType: brainPageEdges.edgeType,
97447
+ weight: brainPageEdges.weight,
97448
+ createdAt: brainPageEdges.createdAt
97449
+ }).from(brainPageEdges);
97450
+ edges = rawEdges.map((e) => ({ ...e, provenance: null }));
97451
+ } catch {
97452
+ edges = [];
97453
+ }
97454
+ const gexf = buildGexfDocument(nodes, edges);
97455
+ return {
97456
+ success: true,
97457
+ format: "gexf",
97458
+ nodeCount: nodes.length,
97459
+ edgeCount: edges.length,
97460
+ content: gexf,
97461
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
97462
+ };
97463
+ }
97464
+ async function exportBrainAsJson(projectRoot) {
97465
+ const db = await getBrainDb(projectRoot);
97466
+ let nodes = [];
97467
+ let edges = [];
97468
+ try {
97469
+ nodes = await db.select({
97470
+ id: brainPageNodes.id,
97471
+ nodeType: brainPageNodes.nodeType,
97472
+ label: brainPageNodes.label,
97473
+ qualityScore: brainPageNodes.qualityScore,
97474
+ contentHash: brainPageNodes.contentHash,
97475
+ lastActivityAt: brainPageNodes.lastActivityAt,
97476
+ metadataJson: brainPageNodes.metadataJson,
97477
+ createdAt: brainPageNodes.createdAt,
97478
+ updatedAt: brainPageNodes.updatedAt
97479
+ }).from(brainPageNodes);
97480
+ } catch {
97481
+ nodes = [];
97482
+ }
97483
+ try {
97484
+ const rawEdges = await db.select({
97485
+ fromId: brainPageEdges.fromId,
97486
+ toId: brainPageEdges.toId,
97487
+ edgeType: brainPageEdges.edgeType,
97488
+ weight: brainPageEdges.weight,
97489
+ createdAt: brainPageEdges.createdAt
97490
+ }).from(brainPageEdges);
97491
+ edges = rawEdges.map((e) => ({ ...e, provenance: null }));
97492
+ } catch {
97493
+ edges = [];
97494
+ }
97495
+ return {
97496
+ success: true,
97497
+ format: "json",
97498
+ nodeCount: nodes.length,
97499
+ edgeCount: edges.length,
97500
+ nodes,
97501
+ edges,
97502
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString()
97503
+ };
97504
+ }
97505
+ function buildGexfDocument(nodes, edges) {
97506
+ const lines = [
97507
+ '<?xml version="1.0" encoding="UTF-8"?>',
97508
+ '<gexf xmlns="http://www.gexf.net/1.3draft" version="1.3">',
97509
+ ' <meta lastmodifieddate="' + (/* @__PURE__ */ new Date()).toISOString() + '">',
97510
+ " <creator>CLEO Brain Export (T626-M6)</creator>",
97511
+ " <description>Living brain knowledge graph (brain_page_nodes + brain_page_edges)</description>",
97512
+ " </meta>",
97513
+ ' <graph mode="static" defaultedgetype="directed">'
97514
+ ];
97515
+ lines.push(' <attributes class="node">');
97516
+ lines.push(' <attribute id="node_type" title="Node Type" type="string"/>');
97517
+ lines.push(' <attribute id="quality_score" title="Quality Score" type="double"/>');
97518
+ lines.push(' <attribute id="content_hash" title="Content Hash" type="string"/>');
97519
+ lines.push(' <attribute id="last_activity_at" title="Last Activity" type="string"/>');
97520
+ lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
97521
+ lines.push(" </attributes>");
97522
+ lines.push(' <attributes class="edge">');
97523
+ lines.push(' <attribute id="edge_type" title="Edge Type" type="string"/>');
97524
+ lines.push(' <attribute id="provenance" title="Provenance" type="string"/>');
97525
+ lines.push(' <attribute id="created_at" title="Created At" type="string"/>');
97526
+ lines.push(" </attributes>");
97527
+ lines.push(" <nodes>");
97528
+ for (const node of nodes) {
97529
+ lines.push(` <node id="${escapeXml(node.id)}" label="${escapeXml(node.label)}">`);
97530
+ lines.push(" <attvalues>");
97531
+ lines.push(` <attvalue for="node_type" value="${escapeXml(node.nodeType)}"/>`);
97532
+ lines.push(` <attvalue for="quality_score" value="${node.qualityScore ?? 0.5}"/>`);
97533
+ if (node.contentHash) {
97534
+ lines.push(` <attvalue for="content_hash" value="${escapeXml(node.contentHash)}"/>`);
97535
+ }
97536
+ lines.push(
97537
+ ` <attvalue for="last_activity_at" value="${escapeXml(node.lastActivityAt)}"/>`
97538
+ );
97539
+ lines.push(` <attvalue for="created_at" value="${escapeXml(node.createdAt)}"/>`);
97540
+ lines.push(" </attvalues>");
97541
+ lines.push(" </node>");
97542
+ }
97543
+ lines.push(" </nodes>");
97544
+ lines.push(" <edges>");
97545
+ for (let i = 0; i < edges.length; i++) {
97546
+ const edge = edges[i];
97547
+ const weight = edge.weight ?? 1;
97548
+ lines.push(
97549
+ ` <edge id="${i}" source="${escapeXml(edge.fromId)}" target="${escapeXml(edge.toId)}" weight="${weight}">`
97550
+ );
97551
+ lines.push(" <attvalues>");
97552
+ lines.push(` <attvalue for="edge_type" value="${escapeXml(edge.edgeType)}"/>`);
97553
+ if (edge.provenance) {
97554
+ lines.push(` <attvalue for="provenance" value="${escapeXml(edge.provenance)}"/>`);
97555
+ }
97556
+ lines.push(` <attvalue for="created_at" value="${escapeXml(edge.createdAt)}"/>`);
97557
+ lines.push(" </attvalues>");
97558
+ lines.push(" </edge>");
97559
+ }
97560
+ lines.push(" </edges>");
97561
+ lines.push(" </graph>");
97562
+ lines.push("</gexf>");
97563
+ return lines.join("\n");
97564
+ }
97565
+ function escapeXml(text3) {
97566
+ return text3.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
97567
+ }
97568
+
96950
97569
  // packages/core/src/internal.ts
96951
97570
  init_brain_lifecycle();
96952
97571
 
@@ -97190,6 +97809,7 @@ async function purgeBrainNoise(projectRoot) {
97190
97809
 
97191
97810
  // packages/core/src/internal.ts
97192
97811
  init_brain_retrieval();
97812
+ init_brain_stdp();
97193
97813
 
97194
97814
  // packages/core/src/memory/claude-mem-migration.ts
97195
97815
  init_paths();
@@ -97365,7 +97985,7 @@ Use --source <path> to specify a custom location.`
97365
97985
  }
97366
97986
  try {
97367
97987
  for (const row of batch) {
97368
- if (!row.learned || !row.learned.trim()) {
97988
+ if (!row.learned?.trim()) {
97369
97989
  continue;
97370
97990
  }
97371
97991
  const learnId = `CML-${row.id}`;
@@ -103723,7 +104343,7 @@ function measureDependencyDepth(taskId, taskMap, visited = /* @__PURE__ */ new S
103723
104343
  if (visited.has(taskId)) return 0;
103724
104344
  visited.add(taskId);
103725
104345
  const task = taskMap.get(taskId);
103726
- if (!task || !task.depends || task.depends.length === 0) return 0;
104346
+ if (!task?.depends || task.depends.length === 0) return 0;
103727
104347
  let maxDepth = 0;
103728
104348
  for (const depId of task.depends) {
103729
104349
  const depth = 1 + measureDependencyDepth(depId, taskMap, visited);
@@ -104077,7 +104697,7 @@ async function coreTaskUnarchive(projectRoot, taskId, params) {
104077
104697
  throw new Error(`Task '${taskId}' already exists in active tasks`);
104078
104698
  }
104079
104699
  const archive = await accessor.loadArchive();
104080
- if (!archive || !archive.archivedTasks) {
104700
+ if (!archive?.archivedTasks) {
104081
104701
  throw new Error("No archive file found");
104082
104702
  }
104083
104703
  const taskIndex = archive.archivedTasks.findIndex((t) => t.id === taskId);
@@ -110309,6 +110929,7 @@ export {
110309
110929
  analyzeDependencies2 as analyzeDependencies,
110310
110930
  analyzeEpic,
110311
110931
  analyzeTaskImpact,
110932
+ applyStdpPlasticity,
110312
110933
  applyStrictnessPreset,
110313
110934
  applyTemporalDecay,
110314
110935
  archiveSessions,
@@ -110522,6 +111143,8 @@ export {
110522
111143
  ensureSqliteDb,
110523
111144
  estimateContext,
110524
111145
  executeTransfer,
111146
+ exportBrainAsGexf,
111147
+ exportBrainAsJson,
110525
111148
  exportSnapshot,
110526
111149
  exportTasks,
110527
111150
  exportTasksPackage,
@@ -110591,7 +111214,7 @@ export {
110591
111214
  getConfigValue,
110592
111215
  getContextDrift,
110593
111216
  getCriticalPath,
110594
- getCurrentSessionId,
111217
+ getCurrentSessionId2 as getCurrentSessionId,
110595
111218
  getDashboard,
110596
111219
  getDb,
110597
111220
  getDecisionLog,
@@ -110636,6 +111259,7 @@ export {
110636
111259
  getPackageRoot,
110637
111260
  getParallelStatus,
110638
111261
  getPipelineStageOrder,
111262
+ getPlasticityStats,
110639
111263
  getProjectAgentRef2 as getProjectAgentRef,
110640
111264
  getProjectInfo,
110641
111265
  getProjectInfoSync,