musememory 1.7.0 → 1.8.0

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 (3) hide show
  1. package/README.md +72 -23
  2. package/dist/index.js +653 -287
  3. package/package.json +1 -2
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ var __create = Object.create;
4
4
  var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
9
  function __accessProp(key) {
9
10
  return this[key];
@@ -32,6 +33,23 @@ var __toESM = (mod, isNodeMode, target) => {
32
33
  cache.set(mod, to);
33
34
  return to;
34
35
  };
36
+ var __toCommonJS = (from) => {
37
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
38
+ if (entry)
39
+ return entry;
40
+ entry = __defProp({}, "__esModule", { value: true });
41
+ if (from && typeof from === "object" || typeof from === "function") {
42
+ for (var key of __getOwnPropNames(from))
43
+ if (!__hasOwnProp.call(entry, key))
44
+ __defProp(entry, key, {
45
+ get: __accessProp.bind(from, key),
46
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
47
+ });
48
+ }
49
+ __moduleCache.set(from, entry);
50
+ return entry;
51
+ };
52
+ var __moduleCache;
35
53
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
36
54
  var __returnValue = (v) => v;
37
55
  function __exportSetter(name, newValue) {
@@ -3511,9 +3529,256 @@ var init_types = __esm(() => {
3511
3529
  };
3512
3530
  });
3513
3531
 
3532
+ // src/graph.ts
3533
+ var exports_graph = {};
3534
+ __export(exports_graph, {
3535
+ autoStampGraphMetadata: () => autoStampGraphMetadata,
3536
+ detectGraphProvider: () => detectGraphProvider,
3537
+ detectProvider: () => detectProvider,
3538
+ extractReferencedSymbols: () => extractReferencedSymbols,
3539
+ getGraphStatus: () => getGraphStatus,
3540
+ getRuntimeTrustVerdict: () => getRuntimeTrustVerdict,
3541
+ graphSymbolsPath: () => graphSymbolsPath,
3542
+ indexGraph: () => indexGraph,
3543
+ loadGraphSymbolIndex: () => loadGraphSymbolIndex,
3544
+ verifyRuntimeFiles: () => verifyRuntimeFiles
3545
+ });
3546
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "node:fs";
3547
+ import { join as join4, isAbsolute } from "node:path";
3548
+ function detectProvider(projectRoot) {
3549
+ if (!projectRoot || !existsSync4(projectRoot))
3550
+ return "none";
3551
+ if (existsSync4(join4(projectRoot, ".codegraph"))) {
3552
+ return "codegraph";
3553
+ }
3554
+ if (existsSync4(join4(projectRoot, ".graphify"))) {
3555
+ return "graphify";
3556
+ }
3557
+ return "none";
3558
+ }
3559
+ function getGraphStatus(projectRoot) {
3560
+ const provider = detectProvider(projectRoot);
3561
+ if (provider === "codegraph") {
3562
+ const codegraphDir = join4(projectRoot, ".codegraph");
3563
+ let symbolCount;
3564
+ let graphRevision;
3565
+ try {
3566
+ if (existsSync4(codegraphDir)) {
3567
+ const files = readdirSync(codegraphDir);
3568
+ symbolCount = files.length;
3569
+ const metaPath = join4(codegraphDir, "meta.json");
3570
+ if (existsSync4(metaPath)) {
3571
+ const meta = JSON.parse(readFileSync4(metaPath, "utf8"));
3572
+ graphRevision = meta.revision ?? meta.commit ?? meta.version;
3573
+ }
3574
+ }
3575
+ } catch {}
3576
+ return {
3577
+ provider: "codegraph",
3578
+ available: true,
3579
+ root: codegraphDir,
3580
+ graphRevision,
3581
+ symbolCount
3582
+ };
3583
+ }
3584
+ if (provider === "graphify") {
3585
+ const graphifyDir = join4(projectRoot, ".graphify");
3586
+ let symbolCount;
3587
+ let graphRevision;
3588
+ try {
3589
+ if (existsSync4(graphifyDir)) {
3590
+ const files = readdirSync(graphifyDir);
3591
+ symbolCount = files.length;
3592
+ const metaPath = join4(graphifyDir, "meta.json");
3593
+ if (existsSync4(metaPath)) {
3594
+ const meta = JSON.parse(readFileSync4(metaPath, "utf8"));
3595
+ graphRevision = meta.revision ?? meta.commit ?? meta.version;
3596
+ }
3597
+ }
3598
+ } catch {}
3599
+ return {
3600
+ provider: "graphify",
3601
+ available: true,
3602
+ root: graphifyDir,
3603
+ graphRevision,
3604
+ symbolCount
3605
+ };
3606
+ }
3607
+ return {
3608
+ provider: "none",
3609
+ available: false,
3610
+ root: projectRoot
3611
+ };
3612
+ }
3613
+ function graphSymbolsPath(memoryDir) {
3614
+ return join4(memoryDir, "graph-symbols.json");
3615
+ }
3616
+ function indexGraph(projectRoot, memoryDir) {
3617
+ const status = getGraphStatus(projectRoot);
3618
+ const symbols = {};
3619
+ if (status.provider === "codegraph") {
3620
+ const codegraphDir = join4(projectRoot, ".codegraph");
3621
+ try {
3622
+ const candidates = [
3623
+ join4(codegraphDir, "symbols.json"),
3624
+ join4(codegraphDir, "index.json"),
3625
+ join4(codegraphDir, "graph.json")
3626
+ ];
3627
+ for (const c of candidates) {
3628
+ if (existsSync4(c)) {
3629
+ const data = JSON.parse(readFileSync4(c, "utf8"));
3630
+ if (Array.isArray(data)) {
3631
+ for (const item of data) {
3632
+ if (item.name && item.path) {
3633
+ symbols[String(item.name)] = String(item.path);
3634
+ }
3635
+ }
3636
+ } else if (typeof data === "object" && data !== null) {
3637
+ if (data.symbols && typeof data.symbols === "object") {
3638
+ for (const [k, v] of Object.entries(data.symbols)) {
3639
+ symbols[k] = typeof v === "string" ? v : v?.path || "";
3640
+ }
3641
+ } else {
3642
+ for (const [k, v] of Object.entries(data)) {
3643
+ if (typeof v === "string")
3644
+ symbols[k] = v;
3645
+ }
3646
+ }
3647
+ }
3648
+ }
3649
+ }
3650
+ if (Object.keys(symbols).length === 0 && existsSync4(codegraphDir)) {
3651
+ const files = readdirSync(codegraphDir);
3652
+ for (const file of files) {
3653
+ if (file.endsWith(".json") && file !== "meta.json") {
3654
+ try {
3655
+ const content = JSON.parse(readFileSync4(join4(codegraphDir, file), "utf8"));
3656
+ if (content.name && content.path) {
3657
+ symbols[String(content.name)] = String(content.path);
3658
+ } else if (content.symbols && Array.isArray(content.symbols)) {
3659
+ for (const s of content.symbols) {
3660
+ if (s.name && (s.path || content.path)) {
3661
+ symbols[String(s.name)] = String(s.path || content.path);
3662
+ }
3663
+ }
3664
+ }
3665
+ } catch {}
3666
+ }
3667
+ }
3668
+ }
3669
+ } catch {}
3670
+ } else if (status.provider === "graphify") {
3671
+ const graphifyDir = join4(projectRoot, ".graphify");
3672
+ try {
3673
+ const candidates = [
3674
+ join4(graphifyDir, "graph.json"),
3675
+ join4(graphifyDir, "symbols.json")
3676
+ ];
3677
+ for (const c of candidates) {
3678
+ if (existsSync4(c)) {
3679
+ const data = JSON.parse(readFileSync4(c, "utf8"));
3680
+ if (data.nodes && Array.isArray(data.nodes)) {
3681
+ for (const node of data.nodes) {
3682
+ if (node.name && node.path) {
3683
+ symbols[String(node.name)] = String(node.path);
3684
+ }
3685
+ }
3686
+ }
3687
+ }
3688
+ }
3689
+ } catch {}
3690
+ }
3691
+ const index = {
3692
+ provider: status.provider,
3693
+ indexedAt: new Date().toISOString(),
3694
+ symbolCount: Object.keys(symbols).length,
3695
+ symbols
3696
+ };
3697
+ try {
3698
+ mkdirSync4(memoryDir, { recursive: true });
3699
+ writeFileSync3(graphSymbolsPath(memoryDir), JSON.stringify(index, null, 2), "utf8");
3700
+ } catch {}
3701
+ return index;
3702
+ }
3703
+ function loadGraphSymbolIndex(memoryDir) {
3704
+ const p = graphSymbolsPath(memoryDir);
3705
+ if (!existsSync4(p))
3706
+ return null;
3707
+ try {
3708
+ const raw = readFileSync4(p, "utf8");
3709
+ return JSON.parse(raw);
3710
+ } catch {
3711
+ return null;
3712
+ }
3713
+ }
3714
+ function extractReferencedSymbols(text, memoryDir) {
3715
+ const index = loadGraphSymbolIndex(memoryDir);
3716
+ if (!index || index.symbolCount === 0) {
3717
+ return { symbol_names: [], affected_paths: [], provider: "none" };
3718
+ }
3719
+ const matchedSymbols = new Set;
3720
+ const affectedPaths = new Set;
3721
+ const words = text.match(/[a-zA-Z_$][a-zA-Z0-9_$]*/g) || [];
3722
+ const wordSet = new Set(words);
3723
+ for (const [symbol, path] of Object.entries(index.symbols)) {
3724
+ if (wordSet.has(symbol)) {
3725
+ matchedSymbols.add(symbol);
3726
+ if (path)
3727
+ affectedPaths.add(path);
3728
+ }
3729
+ }
3730
+ return {
3731
+ symbol_names: Array.from(matchedSymbols),
3732
+ affected_paths: Array.from(affectedPaths),
3733
+ provider: index.provider
3734
+ };
3735
+ }
3736
+ function autoStampGraphMetadata(text, memoryDir) {
3737
+ const extracted = extractReferencedSymbols(text, memoryDir);
3738
+ if (extracted.symbol_names.length === 0)
3739
+ return;
3740
+ return {
3741
+ provider: extracted.provider,
3742
+ symbol_names: extracted.symbol_names,
3743
+ affected_paths: extracted.affected_paths,
3744
+ graph_verified_at: new Date().toISOString()
3745
+ };
3746
+ }
3747
+ function verifyRuntimeFiles(entry, workspaceRoot) {
3748
+ const root = workspaceRoot || process.cwd();
3749
+ const affected = entry.graph?.affected_paths || [];
3750
+ if (affected.length === 0) {
3751
+ return { verdict: "STRONG", existingPaths: [], missingPaths: [] };
3752
+ }
3753
+ const existingPaths = [];
3754
+ const missingPaths = [];
3755
+ for (const relPath of affected) {
3756
+ const fullPath = isAbsolute(relPath) ? relPath : join4(root, relPath);
3757
+ if (existsSync4(fullPath)) {
3758
+ existingPaths.push(relPath);
3759
+ } else {
3760
+ missingPaths.push(relPath);
3761
+ }
3762
+ }
3763
+ if (missingPaths.length > 0 && existingPaths.length === 0) {
3764
+ return { verdict: "STALE", existingPaths, missingPaths, details: `Missing: ${missingPaths.join(", ")}` };
3765
+ }
3766
+ if (missingPaths.length > 0) {
3767
+ return { verdict: "WEAK", existingPaths, missingPaths, details: `Partially missing: ${missingPaths.join(", ")}` };
3768
+ }
3769
+ return { verdict: "STRONG", existingPaths, missingPaths };
3770
+ }
3771
+ function getRuntimeTrustVerdict(entry, workspaceRoot) {
3772
+ return verifyRuntimeFiles(entry, workspaceRoot).verdict;
3773
+ }
3774
+ var detectGraphProvider;
3775
+ var init_graph = __esm(() => {
3776
+ detectGraphProvider = detectProvider;
3777
+ });
3778
+
3514
3779
  // src/retrieval.ts
3515
- import { existsSync as existsSync4 } from "node:fs";
3516
- import { join as join4 } from "node:path";
3780
+ import { existsSync as existsSync5 } from "node:fs";
3781
+ import { join as join5 } from "node:path";
3517
3782
  function tokenize(text) {
3518
3783
  if (!text || typeof text !== "string")
3519
3784
  return [];
@@ -3587,7 +3852,7 @@ function graphSymbolOverlapBonus(entry, queryTokens) {
3587
3852
  return 0;
3588
3853
  return Math.min(0.2, matches / queryTokens.length * 0.2);
3589
3854
  }
3590
- function scoreEntry(entry, queryTokens, now) {
3855
+ function scoreEntry(entry, queryTokens, now = Date.now(), workspaceRoot) {
3591
3856
  const app = applicability(entry, queryTokens);
3592
3857
  const statusPenalty = STATUS_PENALTY[entry.status] ?? 0;
3593
3858
  const vLevel = entry.verification?.level ?? "unverified";
@@ -3597,9 +3862,19 @@ function scoreEntry(entry, queryTokens, now) {
3597
3862
  const reinforcementBonus = Math.sign(r) * 0.05 * Math.min(Math.abs(r), 5);
3598
3863
  const dueBonus = dueDateBonus(entry, now);
3599
3864
  const graphBonus = graphSymbolOverlapBonus(entry, queryTokens);
3865
+ let trustAdjustment = 0;
3866
+ if (entry.graph?.affected_paths && entry.graph.affected_paths.length > 0) {
3867
+ const { verifyRuntimeFiles: verifyRuntimeFiles2 } = (init_graph(), __toCommonJS(exports_graph));
3868
+ const verdict = verifyRuntimeFiles2(entry, workspaceRoot);
3869
+ if (verdict.verdict === "STRONG")
3870
+ trustAdjustment = 0.15;
3871
+ else if (verdict.verdict === "STALE")
3872
+ trustAdjustment = -0.4;
3873
+ }
3600
3874
  const decayBase = entry.valid_from ?? entry.updated_at;
3601
3875
  const decay = 0.3 * Math.exp(-daysSince(decayBase, now) / 90);
3602
- return app + statusPenalty + verificationBonus + salienceBonus + reinforcementBonus + dueBonus + graphBonus + decay;
3876
+ const zeroMatchPenalty = queryTokens.length > 0 && app === 0 && graphBonus === 0 ? -0.35 : 0;
3877
+ return app + statusPenalty + verificationBonus + salienceBonus + reinforcementBonus + dueBonus + graphBonus + trustAdjustment + decay + zeroMatchPenalty;
3603
3878
  }
3604
3879
  function sortCandidates(candidates, queryTokens, now) {
3605
3880
  return candidates.map((entry) => ({ entry, score: scoreEntry(entry, queryTokens, now) })).sort((a, b) => {
@@ -3719,7 +3994,7 @@ function formatPromptContext(store, memoryDir, query = "", options = {}) {
3719
3994
  }
3720
3995
  parts.push("");
3721
3996
  }
3722
- if (memoryDir && existsSync4(join4(memoryDir, "wiki"))) {
3997
+ if (memoryDir && existsSync5(join5(memoryDir, "wiki"))) {
3723
3998
  try {
3724
3999
  const wikiPages = listWikiPages(memoryDir, { detailLevel: "l1", project: options.project });
3725
4000
  if (wikiPages.length > 0) {
@@ -3979,17 +4254,17 @@ var init_retrieval = __esm(() => {
3979
4254
  });
3980
4255
 
3981
4256
  // src/governor.ts
3982
- import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "node:fs";
3983
- import { join as join5 } from "node:path";
4257
+ import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "node:fs";
4258
+ import { join as join6 } from "node:path";
3984
4259
  import { execSync } from "node:child_process";
3985
4260
  function currentFilePath(memoryDir) {
3986
- return join5(memoryDir, "CURRENT.md");
4261
+ return join6(memoryDir, "CURRENT.md");
3987
4262
  }
3988
4263
  function parseCurrentFile(memoryDir) {
3989
4264
  const p = currentFilePath(memoryDir);
3990
- if (!existsSync5(p))
4265
+ if (!existsSync6(p))
3991
4266
  return { constraints: [], handoff: null };
3992
- const raw = readFileSync4(p, "utf8");
4267
+ const raw = readFileSync5(p, "utf8");
3993
4268
  const lines = raw.split(`
3994
4269
  `);
3995
4270
  const constraints = [];
@@ -4079,7 +4354,7 @@ function parseCurrentFile(memoryDir) {
4079
4354
  }
4080
4355
  function writeCurrentFile(memoryDir, data) {
4081
4356
  const p = currentFilePath(memoryDir);
4082
- mkdirSync4(memoryDir, { recursive: true });
4357
+ mkdirSync5(memoryDir, { recursive: true });
4083
4358
  const parts = [`# Active Project Constraints & In-Flight Context
4084
4359
  `];
4085
4360
  parts.push("## Active Working Invariants & Hard Constraints");
@@ -4118,7 +4393,7 @@ function writeCurrentFile(memoryDir, data) {
4118
4393
  }
4119
4394
  parts.push("");
4120
4395
  }
4121
- writeFileSync3(p, parts.join(`
4396
+ writeFileSync4(p, parts.join(`
4122
4397
  `), "utf8");
4123
4398
  }
4124
4399
  function updateSessionHandoff(memoryDir, update) {
@@ -4422,7 +4697,7 @@ var init_current = __esm(() => {
4422
4697
  });
4423
4698
 
4424
4699
  // src/transcript.ts
4425
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
4700
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
4426
4701
  function parseJsonlTranscript(jsonlText) {
4427
4702
  if (!jsonlText)
4428
4703
  return [];
@@ -4473,8 +4748,8 @@ function parseJsonlTranscript(jsonlText) {
4473
4748
  }
4474
4749
  function searchTranscriptWithBookends(transcriptPathOrContent, query, options = {}) {
4475
4750
  let content = transcriptPathOrContent;
4476
- if (existsSync6(transcriptPathOrContent)) {
4477
- content = readFileSync5(transcriptPathOrContent, "utf8");
4751
+ if (existsSync7(transcriptPathOrContent)) {
4752
+ content = readFileSync6(transcriptPathOrContent, "utf8");
4478
4753
  }
4479
4754
  const turns = parseJsonlTranscript(content);
4480
4755
  if (turns.length === 0) {
@@ -4544,7 +4819,7 @@ ${m.matchedTurn}`);
4544
4819
  var init_transcript = () => {};
4545
4820
 
4546
4821
  // src/harvest.ts
4547
- import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
4822
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
4548
4823
  import { createHash } from "node:crypto";
4549
4824
  function extractHarvestUnits(text) {
4550
4825
  if (!text || typeof text !== "string")
@@ -4679,8 +4954,8 @@ function openLoopId(text) {
4679
4954
  }
4680
4955
  function importTranscript(store, transcriptPathOrContent, options = {}) {
4681
4956
  let content = transcriptPathOrContent;
4682
- if (existsSync7(transcriptPathOrContent)) {
4683
- content = readFileSync6(transcriptPathOrContent, "utf8");
4957
+ if (existsSync8(transcriptPathOrContent)) {
4958
+ content = readFileSync7(transcriptPathOrContent, "utf8");
4684
4959
  }
4685
4960
  const blocks = parseJsonlTranscript(content);
4686
4961
  const fullText = blocks.join(`
@@ -4758,210 +5033,6 @@ var init_harvest = __esm(() => {
4758
5033
  ];
4759
5034
  });
4760
5035
 
4761
- // src/graph.ts
4762
- import { existsSync as existsSync8, readdirSync, readFileSync as readFileSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync5 } from "node:fs";
4763
- import { join as join6 } from "node:path";
4764
- function detectProvider(projectRoot) {
4765
- if (!projectRoot || !existsSync8(projectRoot))
4766
- return "none";
4767
- if (existsSync8(join6(projectRoot, ".codegraph"))) {
4768
- return "codegraph";
4769
- }
4770
- if (existsSync8(join6(projectRoot, ".graphify"))) {
4771
- return "graphify";
4772
- }
4773
- return "none";
4774
- }
4775
- function getGraphStatus(projectRoot) {
4776
- const provider = detectProvider(projectRoot);
4777
- if (provider === "codegraph") {
4778
- const codegraphDir = join6(projectRoot, ".codegraph");
4779
- let symbolCount;
4780
- let graphRevision;
4781
- try {
4782
- if (existsSync8(codegraphDir)) {
4783
- const files = readdirSync(codegraphDir);
4784
- symbolCount = files.length;
4785
- const metaPath = join6(codegraphDir, "meta.json");
4786
- if (existsSync8(metaPath)) {
4787
- const meta = JSON.parse(readFileSync7(metaPath, "utf8"));
4788
- graphRevision = meta.revision ?? meta.commit ?? meta.version;
4789
- }
4790
- }
4791
- } catch {}
4792
- return {
4793
- provider: "codegraph",
4794
- available: true,
4795
- root: codegraphDir,
4796
- graphRevision,
4797
- symbolCount
4798
- };
4799
- }
4800
- if (provider === "graphify") {
4801
- const graphifyDir = join6(projectRoot, ".graphify");
4802
- let symbolCount;
4803
- let graphRevision;
4804
- try {
4805
- if (existsSync8(graphifyDir)) {
4806
- const files = readdirSync(graphifyDir);
4807
- symbolCount = files.length;
4808
- const metaPath = join6(graphifyDir, "meta.json");
4809
- if (existsSync8(metaPath)) {
4810
- const meta = JSON.parse(readFileSync7(metaPath, "utf8"));
4811
- graphRevision = meta.revision ?? meta.commit ?? meta.version;
4812
- }
4813
- }
4814
- } catch {}
4815
- return {
4816
- provider: "graphify",
4817
- available: true,
4818
- root: graphifyDir,
4819
- graphRevision,
4820
- symbolCount
4821
- };
4822
- }
4823
- return {
4824
- provider: "none",
4825
- available: false,
4826
- root: projectRoot
4827
- };
4828
- }
4829
- function graphSymbolsPath(memoryDir) {
4830
- return join6(memoryDir, "graph-symbols.json");
4831
- }
4832
- function indexGraph(projectRoot, memoryDir) {
4833
- const status = getGraphStatus(projectRoot);
4834
- const symbols = {};
4835
- if (status.provider === "codegraph") {
4836
- const codegraphDir = join6(projectRoot, ".codegraph");
4837
- try {
4838
- const candidates = [
4839
- join6(codegraphDir, "symbols.json"),
4840
- join6(codegraphDir, "index.json"),
4841
- join6(codegraphDir, "graph.json")
4842
- ];
4843
- for (const c of candidates) {
4844
- if (existsSync8(c)) {
4845
- const data = JSON.parse(readFileSync7(c, "utf8"));
4846
- if (Array.isArray(data)) {
4847
- for (const item of data) {
4848
- if (item.name && item.path) {
4849
- symbols[String(item.name)] = String(item.path);
4850
- }
4851
- }
4852
- } else if (typeof data === "object" && data !== null) {
4853
- if (data.symbols && typeof data.symbols === "object") {
4854
- for (const [k, v] of Object.entries(data.symbols)) {
4855
- symbols[k] = typeof v === "string" ? v : v?.path || "";
4856
- }
4857
- } else {
4858
- for (const [k, v] of Object.entries(data)) {
4859
- if (typeof v === "string")
4860
- symbols[k] = v;
4861
- }
4862
- }
4863
- }
4864
- }
4865
- }
4866
- if (Object.keys(symbols).length === 0 && existsSync8(codegraphDir)) {
4867
- const files = readdirSync(codegraphDir);
4868
- for (const file of files) {
4869
- if (file.endsWith(".json") && file !== "meta.json") {
4870
- try {
4871
- const content = JSON.parse(readFileSync7(join6(codegraphDir, file), "utf8"));
4872
- if (content.name && content.path) {
4873
- symbols[String(content.name)] = String(content.path);
4874
- } else if (content.symbols && Array.isArray(content.symbols)) {
4875
- for (const s of content.symbols) {
4876
- if (s.name && (s.path || content.path)) {
4877
- symbols[String(s.name)] = String(s.path || content.path);
4878
- }
4879
- }
4880
- }
4881
- } catch {}
4882
- }
4883
- }
4884
- }
4885
- } catch {}
4886
- } else if (status.provider === "graphify") {
4887
- const graphifyDir = join6(projectRoot, ".graphify");
4888
- try {
4889
- const candidates = [
4890
- join6(graphifyDir, "graph.json"),
4891
- join6(graphifyDir, "symbols.json")
4892
- ];
4893
- for (const c of candidates) {
4894
- if (existsSync8(c)) {
4895
- const data = JSON.parse(readFileSync7(c, "utf8"));
4896
- if (data.nodes && Array.isArray(data.nodes)) {
4897
- for (const node of data.nodes) {
4898
- if (node.name && node.path) {
4899
- symbols[String(node.name)] = String(node.path);
4900
- }
4901
- }
4902
- }
4903
- }
4904
- }
4905
- } catch {}
4906
- }
4907
- const index = {
4908
- provider: status.provider,
4909
- indexedAt: new Date().toISOString(),
4910
- symbolCount: Object.keys(symbols).length,
4911
- symbols
4912
- };
4913
- try {
4914
- mkdirSync5(memoryDir, { recursive: true });
4915
- writeFileSync4(graphSymbolsPath(memoryDir), JSON.stringify(index, null, 2), "utf8");
4916
- } catch {}
4917
- return index;
4918
- }
4919
- function loadGraphSymbolIndex(memoryDir) {
4920
- const p = graphSymbolsPath(memoryDir);
4921
- if (!existsSync8(p))
4922
- return null;
4923
- try {
4924
- const raw = readFileSync7(p, "utf8");
4925
- return JSON.parse(raw);
4926
- } catch {
4927
- return null;
4928
- }
4929
- }
4930
- function extractReferencedSymbols(text, memoryDir) {
4931
- const index = loadGraphSymbolIndex(memoryDir);
4932
- if (!index || index.symbolCount === 0) {
4933
- return { symbol_names: [], affected_paths: [], provider: "none" };
4934
- }
4935
- const matchedSymbols = new Set;
4936
- const affectedPaths = new Set;
4937
- const words = text.match(/[a-zA-Z_$][a-zA-Z0-9_$]*/g) || [];
4938
- const wordSet = new Set(words);
4939
- for (const [symbol, path] of Object.entries(index.symbols)) {
4940
- if (wordSet.has(symbol)) {
4941
- matchedSymbols.add(symbol);
4942
- if (path)
4943
- affectedPaths.add(path);
4944
- }
4945
- }
4946
- return {
4947
- symbol_names: Array.from(matchedSymbols),
4948
- affected_paths: Array.from(affectedPaths),
4949
- provider: index.provider
4950
- };
4951
- }
4952
- function autoStampGraphMetadata(text, memoryDir) {
4953
- const extracted = extractReferencedSymbols(text, memoryDir);
4954
- if (extracted.symbol_names.length === 0)
4955
- return;
4956
- return {
4957
- provider: extracted.provider,
4958
- symbol_names: extracted.symbol_names,
4959
- affected_paths: extracted.affected_paths,
4960
- graph_verified_at: new Date().toISOString()
4961
- };
4962
- }
4963
- var init_graph = () => {};
4964
-
4965
5036
  // src/sqlite.ts
4966
5037
  import { existsSync as existsSync9, mkdirSync as mkdirSync6 } from "node:fs";
4967
5038
  import { dirname } from "node:path";
@@ -6776,6 +6847,9 @@ function ancestorChain(startDir) {
6776
6847
  }
6777
6848
  return chain;
6778
6849
  }
6850
+ function resolveMemoryDir(options = {}) {
6851
+ return findOrCreateProjectRoot(options.root || process.cwd(), options).memoryDir;
6852
+ }
6779
6853
  var MEMORY_DIR_NAMES;
6780
6854
  var init_root = __esm(() => {
6781
6855
  init_user();
@@ -26553,6 +26627,211 @@ var init_settings2 = __esm(() => {
26553
26627
  init_settings();
26554
26628
  });
26555
26629
 
26630
+ // src/plasticity.ts
26631
+ var exports_plasticity = {};
26632
+ __export(exports_plasticity, {
26633
+ getAssociatedMemories: () => getAssociatedMemories,
26634
+ getHebbianAssociationWeight: () => getHebbianAssociationWeight,
26635
+ loadHebbianGraph: () => loadHebbianGraph,
26636
+ recordCoActivation: () => recordCoActivation,
26637
+ saveHebbianGraph: () => saveHebbianGraph
26638
+ });
26639
+ import { existsSync as existsSync30, readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
26640
+ import { join as join27 } from "node:path";
26641
+ function getPlasticityPath(memoryDir) {
26642
+ return join27(memoryDir, "hebbian-plasticity.json");
26643
+ }
26644
+ function loadHebbianGraph(memoryDir) {
26645
+ const p = getPlasticityPath(memoryDir);
26646
+ if (!existsSync30(p))
26647
+ return {};
26648
+ try {
26649
+ return JSON.parse(readFileSync24(p, "utf8"));
26650
+ } catch {
26651
+ return {};
26652
+ }
26653
+ }
26654
+ function saveHebbianGraph(memoryDir, graph) {
26655
+ const p = getPlasticityPath(memoryDir);
26656
+ try {
26657
+ writeFileSync16(p, JSON.stringify(graph, null, 2), "utf8");
26658
+ } catch {}
26659
+ }
26660
+ function recordCoActivation(memoryIds, memoryDir) {
26661
+ const ids = Array.from(new Set(memoryIds.filter(Boolean)));
26662
+ if (ids.length < 2)
26663
+ return;
26664
+ const graph = loadHebbianGraph(memoryDir);
26665
+ const now = new Date().toISOString();
26666
+ for (let i = 0;i < ids.length; i++) {
26667
+ const src = ids[i];
26668
+ if (!graph[src])
26669
+ graph[src] = {};
26670
+ for (let j = 0;j < ids.length; j++) {
26671
+ if (i === j)
26672
+ continue;
26673
+ const tgt = ids[j];
26674
+ const existing = graph[src][tgt];
26675
+ const prevWeight = existing ? existing.weight : 0;
26676
+ const prevCount = existing ? existing.count : 0;
26677
+ const newWeight = Math.min(1, Math.round((prevWeight + 0.05) * 1000) / 1000);
26678
+ graph[src][tgt] = {
26679
+ weight: newWeight,
26680
+ count: prevCount + 1,
26681
+ lastActivated: now
26682
+ };
26683
+ }
26684
+ }
26685
+ saveHebbianGraph(memoryDir, graph);
26686
+ }
26687
+ function getHebbianAssociationWeight(sourceId, targetId, memoryDir) {
26688
+ const graph = loadHebbianGraph(memoryDir);
26689
+ return graph[sourceId]?.[targetId]?.weight ?? 0;
26690
+ }
26691
+ function getAssociatedMemories(sourceId, memoryDir) {
26692
+ const graph = loadHebbianGraph(memoryDir);
26693
+ const targets = graph[sourceId];
26694
+ if (!targets)
26695
+ return [];
26696
+ return Object.entries(targets).map(([targetId, edge]) => ({
26697
+ targetId,
26698
+ weight: edge.weight,
26699
+ count: edge.count
26700
+ })).sort((a, b) => b.weight - a.weight);
26701
+ }
26702
+ var init_plasticity = () => {};
26703
+
26704
+ // src/compress.ts
26705
+ var exports_compress = {};
26706
+ __export(exports_compress, {
26707
+ compressPromptContext: () => compressPromptContext,
26708
+ estimateTokens: () => estimateTokens
26709
+ });
26710
+ function estimateTokens(text) {
26711
+ if (!text || text.trim().length === 0)
26712
+ return 0;
26713
+ return Math.max(1, Math.ceil(text.length / 4));
26714
+ }
26715
+ function compressPromptContext(text, options = {}) {
26716
+ if (!text || text.trim().length === 0) {
26717
+ return {
26718
+ compressed: "",
26719
+ originalTokens: 0,
26720
+ compressedTokens: 0,
26721
+ savingsPercent: 0
26722
+ };
26723
+ }
26724
+ const originalTokens = estimateTokens(text);
26725
+ let cleaned = text.replace(/\n\s*\n\s*\n+/g, `
26726
+
26727
+ `).replace(/### Active Working Constraints \(CURRENT\.md\)/gi, "### Active Constraints").replace(/### Active In-Flight Context & Session Handoff \(CURRENT\.md\)/gi, "### In-Flight Handoff").replace(/### User Profile & Preferences \(USER\.md\)/gi, "### User Profile").replace(/### Relevant Memories & Learned Patterns/gi, "### Memories").replace(/\n\s*---\s*\n/g, `
26728
+ `).replace(/\*Memory Directive: When learning durable facts[^\n]*\*/gi, "").replace(/[ \t]{2,}/g, " ").trim();
26729
+ const compressedTokens = estimateTokens(cleaned);
26730
+ const diff = originalTokens - compressedTokens;
26731
+ const savingsPercent = originalTokens > 0 ? Math.round(Math.max(0, diff) / originalTokens * 100) : 0;
26732
+ return {
26733
+ compressed: cleaned,
26734
+ originalTokens,
26735
+ compressedTokens,
26736
+ savingsPercent
26737
+ };
26738
+ }
26739
+
26740
+ // src/drift.ts
26741
+ var exports_drift = {};
26742
+ __export(exports_drift, {
26743
+ getGitChangedFiles: () => getGitChangedFiles,
26744
+ scanCodeDrift: () => scanCodeDrift,
26745
+ scanCodeDriftFromDiff: () => scanCodeDriftFromDiff
26746
+ });
26747
+ import { execSync as execSync2 } from "node:child_process";
26748
+ import { existsSync as existsSync31 } from "node:fs";
26749
+ import { join as join28, isAbsolute as isAbsolute2 } from "node:path";
26750
+ function scanCodeDriftFromDiff(entries, changedFiles, workspaceRoot) {
26751
+ const root = workspaceRoot || process.cwd();
26752
+ const normalizedChanged = new Set(changedFiles.map((f) => f.trim().replace(/^[\.\/]+/, "")).filter(Boolean));
26753
+ const drifted = [];
26754
+ for (const entry of entries) {
26755
+ if (entry.status !== "confirmed" && entry.status !== "candidate")
26756
+ continue;
26757
+ const paths = entry.graph?.affected_paths || [];
26758
+ const symbols = entry.graph?.symbol_names || [];
26759
+ for (const p of paths) {
26760
+ const norm = p.trim().replace(/^[\.\/]+/, "");
26761
+ const matched = Array.from(normalizedChanged).find((cf) => cf === norm || cf.endsWith(`/${norm}`) || norm.endsWith(`/${cf}`));
26762
+ if (matched) {
26763
+ const fullPath = isAbsolute2(p) ? p : join28(root, p);
26764
+ const exists = existsSync31(fullPath);
26765
+ drifted.push({
26766
+ memoryId: entry.id,
26767
+ title: entry.title,
26768
+ affectedPath: p,
26769
+ symbols,
26770
+ driftType: exists ? "modified" : "deleted",
26771
+ suggestedAction: exists ? "verify" : "mark_stale"
26772
+ });
26773
+ break;
26774
+ }
26775
+ }
26776
+ }
26777
+ return {
26778
+ isDrifted: drifted.length > 0,
26779
+ driftCount: drifted.length,
26780
+ driftedMemories: drifted,
26781
+ scannedFilesCount: normalizedChanged.size,
26782
+ changedFiles: Array.from(normalizedChanged)
26783
+ };
26784
+ }
26785
+ function getGitChangedFiles(workspaceRoot) {
26786
+ const root = workspaceRoot || process.cwd();
26787
+ try {
26788
+ const stdout = execSync2("git status --porcelain", {
26789
+ cwd: root,
26790
+ encoding: "utf8",
26791
+ stdio: ["ignore", "pipe", "ignore"]
26792
+ });
26793
+ const files = [];
26794
+ for (const line of stdout.split(`
26795
+ `)) {
26796
+ const trimmed = line.trim();
26797
+ if (!trimmed)
26798
+ continue;
26799
+ const parts = trimmed.split(/\s+/);
26800
+ const filePath = parts.length >= 2 ? parts[parts.length - 1] : "";
26801
+ if (filePath)
26802
+ files.push(filePath);
26803
+ }
26804
+ try {
26805
+ const diffOut = execSync2("git diff --name-only HEAD", {
26806
+ cwd: root,
26807
+ encoding: "utf8",
26808
+ stdio: ["ignore", "pipe", "ignore"]
26809
+ });
26810
+ for (const line of diffOut.split(`
26811
+ `)) {
26812
+ const f = line.trim();
26813
+ if (f && !files.includes(f))
26814
+ files.push(f);
26815
+ }
26816
+ } catch {}
26817
+ return files;
26818
+ } catch {
26819
+ return [];
26820
+ }
26821
+ }
26822
+ function scanCodeDrift(options = {}) {
26823
+ const root = options.workspaceRoot || process.cwd();
26824
+ const changedFiles = getGitChangedFiles(root);
26825
+ const memDir = options.memoryDir || resolveMemoryDir({ global: false, root });
26826
+ const store = openStore(memDir);
26827
+ const entries = list(store);
26828
+ return scanCodeDriftFromDiff(entries, changedFiles, root);
26829
+ }
26830
+ var init_drift = __esm(() => {
26831
+ init_store();
26832
+ init_root();
26833
+ });
26834
+
26556
26835
  // src/mcp.ts
26557
26836
  var exports_mcp = {};
26558
26837
  __export(exports_mcp, {
@@ -27163,6 +27442,28 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
27163
27442
  },
27164
27443
  required: ["settings"]
27165
27444
  }
27445
+ },
27446
+ {
27447
+ name: "memory_drift",
27448
+ description: "Scan the local Git workspace for modified or deleted code files and AST symbols referenced by memories. Flags drifted memories for re-verification or supersession.",
27449
+ inputSchema: {
27450
+ type: "object",
27451
+ properties: {
27452
+ dir: { type: "string", description: "Optional project workspace directory path" }
27453
+ }
27454
+ }
27455
+ },
27456
+ {
27457
+ name: "memory_compress",
27458
+ description: "Compress formatted prompt context losslessly, stripping header whitespace and boilerplate while preserving all architectural facts.",
27459
+ inputSchema: {
27460
+ type: "object",
27461
+ properties: {
27462
+ text: { type: "string", description: "Markdown prompt context to compress" },
27463
+ level: { type: "string", enum: ["light", "aggressive"], description: "Compression aggressiveness level" }
27464
+ },
27465
+ required: ["text"]
27466
+ }
27166
27467
  }
27167
27468
  ]
27168
27469
  }));
@@ -27200,8 +27501,19 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
27200
27501
  verified: a.verified === true,
27201
27502
  depth: a.depth ? String(a.depth) : undefined
27202
27503
  });
27504
+ if (formatted.entries.length >= 2 && activeMemoryDir) {
27505
+ try {
27506
+ const { recordCoActivation: recordCoActivation2 } = await Promise.resolve().then(() => (init_plasticity(), exports_plasticity));
27507
+ recordCoActivation2(formatted.entries.map((e) => e.entry.id), activeMemoryDir);
27508
+ } catch {}
27509
+ }
27510
+ let finalMarkdown = formatted.markdown;
27511
+ if (a.compress === true) {
27512
+ const { compressPromptContext: compressPromptContext2 } = await Promise.resolve().then(() => exports_compress);
27513
+ finalMarkdown = compressPromptContext2(finalMarkdown).compressed;
27514
+ }
27203
27515
  return toolResult({
27204
- markdown: formatted.markdown,
27516
+ markdown: finalMarkdown,
27205
27517
  entries: formatted.entries.map((r) => ({ ...r.entry, score: r.score })),
27206
27518
  total_tokens_used: formatted.totalTokensUsed,
27207
27519
  constraints: formatted.constraints,
@@ -27635,6 +27947,18 @@ Path: ${item.path}`,
27635
27947
  return toolError(err instanceof Error ? err.message : String(err));
27636
27948
  }
27637
27949
  }
27950
+ case "memory_drift": {
27951
+ const { scanCodeDrift: scanCodeDrift2 } = await Promise.resolve().then(() => (init_drift(), exports_drift));
27952
+ const report = scanCodeDrift2({ workspaceRoot: activeRoot, memoryDir: activeMemoryDir });
27953
+ return toolResult(report);
27954
+ }
27955
+ case "memory_compress": {
27956
+ const { compressPromptContext: compressPromptContext2 } = await Promise.resolve().then(() => exports_compress);
27957
+ const text = String(a.text ?? "");
27958
+ const level = a.level === "aggressive" ? "aggressive" : "light";
27959
+ const result = compressPromptContext2(text, { level });
27960
+ return toolResult(result);
27961
+ }
27638
27962
  default:
27639
27963
  return toolError(`unknown tool ${name}`);
27640
27964
  }
@@ -27699,8 +28023,8 @@ __export(exports_daemon, {
27699
28023
  startHub: () => startHub
27700
28024
  });
27701
28025
  import { createServer as createServer2 } from "node:http";
27702
- import { existsSync as existsSync30 } from "node:fs";
27703
- import { join as join27 } from "node:path";
28026
+ import { existsSync as existsSync32 } from "node:fs";
28027
+ import { join as join29 } from "node:path";
27704
28028
  import { watch } from "node:fs";
27705
28029
  function startHub(port, memoryDir) {
27706
28030
  const clients = new Set;
@@ -27766,7 +28090,7 @@ data: ${JSON.stringify(event)}
27766
28090
  return clients.size;
27767
28091
  }
27768
28092
  if (memoryDir) {
27769
- const memoriesDir = join27(memoryDir, "memories");
28093
+ const memoriesDir = join29(memoryDir, "memories");
27770
28094
  const armDebounced = (type2) => {
27771
28095
  if (debounceTimer)
27772
28096
  clearTimeout(debounceTimer);
@@ -27775,11 +28099,11 @@ data: ${JSON.stringify(event)}
27775
28099
  }, DEBOUNCE_MS);
27776
28100
  };
27777
28101
  try {
27778
- if (existsSync30(memoriesDir)) {
28102
+ if (existsSync32(memoriesDir)) {
27779
28103
  watchers.push(watch(memoriesDir, () => armDebounced("memory.changed")));
27780
28104
  }
27781
- const currentMd = join27(memoryDir, "CURRENT.md");
27782
- if (existsSync30(currentMd)) {
28105
+ const currentMd = join29(memoryDir, "CURRENT.md");
28106
+ if (existsSync32(currentMd)) {
27783
28107
  watchers.push(watch(currentMd, () => armDebounced("constraints.changed")));
27784
28108
  }
27785
28109
  } catch {}
@@ -27812,19 +28136,19 @@ var DEBOUNCE_MS = 300;
27812
28136
  var init_daemon = () => {};
27813
28137
 
27814
28138
  // src/cli/ecosystem.ts
27815
- import { join as join28 } from "node:path";
27816
- import { existsSync as existsSync31, mkdirSync as mkdirSync18, writeFileSync as writeFileSync16, readFileSync as readFileSync24 } from "node:fs";
28139
+ import { join as join30 } from "node:path";
28140
+ import { existsSync as existsSync33, mkdirSync as mkdirSync18, writeFileSync as writeFileSync17, readFileSync as readFileSync25 } from "node:fs";
27817
28141
  import { homedir as homedir6 } from "node:os";
27818
28142
  function ensureProjectAgentInstructions(targetDir) {
27819
- const agentsMdPath = join28(targetDir, "AGENTS.md");
27820
- if (existsSync31(agentsMdPath)) {
28143
+ const agentsMdPath = join30(targetDir, "AGENTS.md");
28144
+ if (existsSync33(agentsMdPath)) {
27821
28145
  try {
27822
- const existing = readFileSync24(agentsMdPath, "utf8");
28146
+ const existing = readFileSync25(agentsMdPath, "utf8");
27823
28147
  if (existing.includes("<!-- agentmemory:start -->")) {
27824
28148
  const updated = existing.replace(/<!-- agentmemory:start -->[\s\S]*?<!-- agentmemory:end -->/, MUSE_MEMORY_DIRECTIVE);
27825
- writeFileSync16(agentsMdPath, updated, "utf8");
28149
+ writeFileSync17(agentsMdPath, updated, "utf8");
27826
28150
  } else if (!existing.includes("<!-- musememory:start -->") && !existing.includes("Muse Memory")) {
27827
- writeFileSync16(agentsMdPath, `${existing.trim()}
28151
+ writeFileSync17(agentsMdPath, `${existing.trim()}
27828
28152
 
27829
28153
  ${MUSE_MEMORY_DIRECTIVE}
27830
28154
  `, "utf8");
@@ -27835,23 +28159,23 @@ ${MUSE_MEMORY_DIRECTIVE}
27835
28159
 
27836
28160
  ${MUSE_MEMORY_DIRECTIVE}
27837
28161
  `;
27838
- writeFileSync16(agentsMdPath, initialContent, "utf8");
28162
+ writeFileSync17(agentsMdPath, initialContent, "utf8");
27839
28163
  }
27840
28164
  }
27841
28165
  async function handleInstallCommand({ positional, flags }) {
27842
28166
  const isGlobal = flags["global"] === "true" || flags["g"] === "true";
27843
- const targetDir = positional[0] ? join28(process.cwd(), positional[0]) : process.cwd();
27844
- const memoryDir = isGlobal ? getGlobalMemoryDir() : join28(targetDir, ".memory");
28167
+ const targetDir = positional[0] ? join30(process.cwd(), positional[0]) : process.cwd();
28168
+ const memoryDir = isGlobal ? getGlobalMemoryDir() : join30(targetDir, ".memory");
27845
28169
  const globalDir = getGlobalMemoryDir();
27846
- mkdirSync18(join28(memoryDir, "memories"), { recursive: true });
27847
- mkdirSync18(join28(globalDir, "memories"), { recursive: true });
27848
- const currentPath = join28(memoryDir, "CURRENT.md");
27849
- if (!existsSync31(currentPath)) {
27850
- writeFileSync16(currentPath, `# Active Project Constraints
28170
+ mkdirSync18(join30(memoryDir, "memories"), { recursive: true });
28171
+ mkdirSync18(join30(globalDir, "memories"), { recursive: true });
28172
+ const currentPath = join30(memoryDir, "CURRENT.md");
28173
+ if (!existsSync33(currentPath)) {
28174
+ writeFileSync17(currentPath, `# Active Project Constraints
27851
28175
  `, "utf8");
27852
28176
  }
27853
28177
  const globalUserPath = userFilePath(globalDir);
27854
- if (!existsSync31(globalUserPath)) {
28178
+ if (!existsSync33(globalUserPath)) {
27855
28179
  const { promptSingleSelect: promptSingleSelect2 } = await Promise.resolve().then(() => (init_prompt(), exports_prompt));
27856
28180
  const archetypeOptions = [
27857
28181
  { id: "developer", label: "Software Engineer / Developer", hint: "Code-first, direct, strict typing" },
@@ -27867,13 +28191,13 @@ async function handleInstallCommand({ positional, flags }) {
27867
28191
  if (!isGlobal) {
27868
28192
  ensureProjectAgentInstructions(targetDir);
27869
28193
  }
27870
- const globalAgentsMd = join28(homedir6(), ".agents", "AGENTS.md");
27871
- if (existsSync31(globalAgentsMd)) {
28194
+ const globalAgentsMd = join30(homedir6(), ".agents", "AGENTS.md");
28195
+ if (existsSync33(globalAgentsMd)) {
27872
28196
  try {
27873
- const existing = readFileSync24(globalAgentsMd, "utf8");
28197
+ const existing = readFileSync25(globalAgentsMd, "utf8");
27874
28198
  if (existing.includes("<!-- agentmemory:start -->")) {
27875
28199
  const updated = existing.replace(/<!-- agentmemory:start -->[\s\S]*?<!-- agentmemory:end -->/, MUSE_MEMORY_DIRECTIVE);
27876
- writeFileSync16(globalAgentsMd, updated, "utf8");
28200
+ writeFileSync17(globalAgentsMd, updated, "utf8");
27877
28201
  }
27878
28202
  } catch {}
27879
28203
  }
@@ -27901,11 +28225,11 @@ async function handleInstallCommand({ positional, flags }) {
27901
28225
  return 0;
27902
28226
  }
27903
28227
  async function promptOrNotifyGitHook(targetDir, autoInstall = false) {
27904
- const gitDir = join28(targetDir, ".git");
27905
- if (!existsSync31(gitDir))
28228
+ const gitDir = join30(targetDir, ".git");
28229
+ if (!existsSync33(gitDir))
27906
28230
  return false;
27907
- const hookPath = join28(gitDir, "hooks", "pre-commit");
27908
- const isInstalled = existsSync31(hookPath) && readFileSync24(hookPath, "utf8").includes("memory harvest-auto");
28231
+ const hookPath = join30(gitDir, "hooks", "pre-commit");
28232
+ const isInstalled = existsSync33(hookPath) && readFileSync25(hookPath, "utf8").includes("memory harvest-auto");
27909
28233
  if (isInstalled)
27910
28234
  return true;
27911
28235
  if (autoInstall) {
@@ -27949,7 +28273,7 @@ async function handleUninstallCommand({ positional, flags }) {
27949
28273
  }
27950
28274
  if (purge) {
27951
28275
  const ctx = requireRoot(flags);
27952
- if (ctx && existsSync31(ctx.memoryDir) && !dryRun) {
28276
+ if (ctx && existsSync33(ctx.memoryDir) && !dryRun) {
27953
28277
  const { rmSync: rmSync3 } = await import("node:fs");
27954
28278
  rmSync3(ctx.memoryDir, { recursive: true, force: true });
27955
28279
  console.log(` [PURGED] Memory directory removed: ${ctx.memoryDir}`);
@@ -27962,13 +28286,13 @@ async function handleUninstallCommand({ positional, flags }) {
27962
28286
  }
27963
28287
  async function handleInitCommand({ positional, flags }) {
27964
28288
  const isGlobal = flags["global"] === "true";
27965
- const targetDir = positional[0] ? join28(process.cwd(), positional[0]) : process.cwd();
28289
+ const targetDir = positional[0] ? join30(process.cwd(), positional[0]) : process.cwd();
27966
28290
  const memoryDirName = flags["legacy"] === "true" ? ".musememory" : ".memory";
27967
- const memoryDir = isGlobal ? getGlobalMemoryDir() : join28(targetDir, memoryDirName);
27968
- mkdirSync18(join28(memoryDir, "memories"), { recursive: true });
27969
- const currentPath = join28(memoryDir, "CURRENT.md");
27970
- if (!existsSync31(currentPath)) {
27971
- writeFileSync16(currentPath, `# Active Project Constraints
28291
+ const memoryDir = isGlobal ? getGlobalMemoryDir() : join30(targetDir, memoryDirName);
28292
+ mkdirSync18(join30(memoryDir, "memories"), { recursive: true });
28293
+ const currentPath = join30(memoryDir, "CURRENT.md");
28294
+ if (!existsSync33(currentPath)) {
28295
+ writeFileSync17(currentPath, `# Active Project Constraints
27972
28296
  `, "utf8");
27973
28297
  }
27974
28298
  if (!isGlobal) {
@@ -28192,9 +28516,46 @@ async function handleDaemonCommand({ flags }) {
28192
28516
  const { startHub: startHub2 } = await Promise.resolve().then(() => (init_daemon(), exports_daemon));
28193
28517
  const hub = await startHub2(port, ctx.memoryDir);
28194
28518
  console.log(`Agency hub listening on ${hub.url}`);
28195
- console.log(`Publish events: curl -X POST http://localhost:${hub.port}/publish -d '{"type":"agent.joined","payload":{"name":"me"}}'`);
28196
28519
  return new Promise(() => {});
28197
28520
  }
28521
+ async function handleDriftCommand({ flags }) {
28522
+ const ctx = requireRoot(flags);
28523
+ if (!ctx)
28524
+ return 1;
28525
+ const { scanCodeDrift: scanCodeDrift2 } = await Promise.resolve().then(() => (init_drift(), exports_drift));
28526
+ const report = scanCodeDrift2({ workspaceRoot: ctx.root, memoryDir: ctx.memoryDir });
28527
+ if (flags["json"] === "true") {
28528
+ console.log(JSON.stringify(report, null, 2));
28529
+ return 0;
28530
+ }
28531
+ console.log(`[Code-Drift Scanner] Scanned ${report.scannedFilesCount} modified/deleted files in Git workspace.`);
28532
+ if (!report.isDrifted) {
28533
+ console.log(`✓ 0 drifted memories. All referenced code symbols and files are intact.`);
28534
+ return 0;
28535
+ }
28536
+ console.log(`⚠️ Detected ${report.driftCount} drifted memories:`);
28537
+ for (const d of report.driftedMemories) {
28538
+ console.log(` - [${d.driftType.toUpperCase()}] ${d.memoryId}: "${d.title}" -> ${d.affectedPath} (action: ${d.suggestedAction})`);
28539
+ }
28540
+ return 0;
28541
+ }
28542
+ async function handleCompressCommand({ positional, flags }) {
28543
+ const text = positional.join(" ") || "";
28544
+ if (!text) {
28545
+ return usageError("compress requires text or input");
28546
+ }
28547
+ const { compressPromptContext: compressPromptContext2 } = await Promise.resolve().then(() => exports_compress);
28548
+ const level = flags["aggressive"] === "true" ? "aggressive" : "light";
28549
+ const result = compressPromptContext2(text, { level });
28550
+ if (flags["json"] === "true") {
28551
+ console.log(JSON.stringify(result, null, 2));
28552
+ return 0;
28553
+ }
28554
+ console.log(`[Prompt Compression] Tokens: ${result.originalTokens} ➔ ${result.compressedTokens} (${result.savingsPercent}% savings)
28555
+ `);
28556
+ console.log(result.compressed);
28557
+ return 0;
28558
+ }
28198
28559
  var MUSE_MEMORY_DIRECTIVE = `<!-- musememory:start -->
28199
28560
  ## \uD83E\uDDE0 Persistent Cognitive Memory (Muse Memory)
28200
28561
 
@@ -28215,8 +28576,8 @@ var init_ecosystem = __esm(() => {
28215
28576
  });
28216
28577
 
28217
28578
  // src/agentcontract.ts
28218
- import { existsSync as existsSync32 } from "node:fs";
28219
- import { join as join29 } from "node:path";
28579
+ import { existsSync as existsSync34 } from "node:fs";
28580
+ import { join as join31 } from "node:path";
28220
28581
  function parseAgentMemoryContract(markdown) {
28221
28582
  if (!markdown || !markdown.startsWith("---"))
28222
28583
  return null;
@@ -28248,17 +28609,17 @@ function parseAgentMemoryContract(markdown) {
28248
28609
  function resolveAgentFile(nameOrPath, workspaceRoot) {
28249
28610
  if (!nameOrPath)
28250
28611
  return null;
28251
- if (existsSync32(nameOrPath))
28612
+ if (existsSync34(nameOrPath))
28252
28613
  return nameOrPath;
28253
28614
  const candidates = [
28254
- join29(workspaceRoot, ".agents", `${nameOrPath}.md`),
28255
- join29(workspaceRoot, ".memory", "agents", `${nameOrPath}.md`)
28615
+ join31(workspaceRoot, ".agents", `${nameOrPath}.md`),
28616
+ join31(workspaceRoot, ".memory", "agents", `${nameOrPath}.md`)
28256
28617
  ];
28257
28618
  const home = process.env.HOME;
28258
28619
  if (home)
28259
- candidates.push(join29(home, ".config", "opencode", "agents", `${nameOrPath}.md`));
28620
+ candidates.push(join31(home, ".config", "opencode", "agents", `${nameOrPath}.md`));
28260
28621
  for (const c of candidates) {
28261
- if (existsSync32(c))
28622
+ if (existsSync34(c))
28262
28623
  return c;
28263
28624
  }
28264
28625
  return null;
@@ -28268,8 +28629,8 @@ var init_agentcontract = __esm(() => {
28268
28629
  });
28269
28630
 
28270
28631
  // src/cli/retrieval.ts
28271
- import { existsSync as existsSync33, readFileSync as readFileSync25 } from "node:fs";
28272
- import { join as join30 } from "node:path";
28632
+ import { existsSync as existsSync35, readFileSync as readFileSync26 } from "node:fs";
28633
+ import { join as join32 } from "node:path";
28273
28634
  async function handleContextCommand({ positional, flags }) {
28274
28635
  let agentTypes;
28275
28636
  let agentTags;
@@ -28277,7 +28638,7 @@ async function handleContextCommand({ positional, flags }) {
28277
28638
  const file = resolveAgentFile(flags["for-agent"], flags["dir"] ?? process.cwd());
28278
28639
  if (!file)
28279
28640
  return usageError(`--for-agent: cannot resolve agent '${flags["for-agent"]}'`);
28280
- const contract = parseAgentMemoryContract(readFileSync25(file, "utf8"));
28641
+ const contract = parseAgentMemoryContract(readFileSync26(file, "utf8"));
28281
28642
  if (contract) {
28282
28643
  agentTypes = contract.types;
28283
28644
  agentTags = contract.tags;
@@ -28417,7 +28778,7 @@ async function handleHarvestCommand({ positional, flags }) {
28417
28778
  const project = flags["project"];
28418
28779
  if (!project)
28419
28780
  return usageError("harvest requires --project");
28420
- const rawText = existsSync33(target) ? readFileSync25(target, "utf8") : target;
28781
+ const rawText = existsSync35(target) ? readFileSync26(target, "utf8") : target;
28421
28782
  const created = harvestMemories(ctx.store, {
28422
28783
  text: rawText,
28423
28784
  project,
@@ -28453,8 +28814,8 @@ async function handleSearchTranscriptCommand({ positional, flags }) {
28453
28814
  const filePath = positional[1];
28454
28815
  if (!query)
28455
28816
  return usageError("search-transcript requires <query> [file.jsonl]");
28456
- const targetFile = filePath ? filePath.startsWith("/") ? filePath : join30(process.cwd(), filePath) : join30(process.cwd(), "transcript.jsonl");
28457
- if (!existsSync33(targetFile)) {
28817
+ const targetFile = filePath ? filePath.startsWith("/") ? filePath : join32(process.cwd(), filePath) : join32(process.cwd(), "transcript.jsonl");
28818
+ if (!existsSync35(targetFile)) {
28458
28819
  return fail(`error: transcript file not found: ${targetFile}`);
28459
28820
  }
28460
28821
  const windowSize = flags["window"] ? parseInt(flags["window"], 10) : 2;
@@ -28470,7 +28831,7 @@ async function handleReindexCommand({ flags }) {
28470
28831
  const { rebuildIndex: rebuildIndex2, saveIndex: saveIndex2 } = await Promise.resolve().then(() => (init_vector(), exports_vector));
28471
28832
  const index = rebuildIndex2(ctx.store);
28472
28833
  saveIndex2(index, ctx.memoryDir);
28473
- console.log(`indexed ${Object.keys(index.entries).length} entries -> ${join30(ctx.memoryDir, "index.json")}`);
28834
+ console.log(`indexed ${Object.keys(index.entries).length} entries -> ${join32(ctx.memoryDir, "index.json")}`);
28474
28835
  return 0;
28475
28836
  }
28476
28837
  async function handleHookCommand({ positional, flags }) {
@@ -28861,7 +29222,7 @@ var init_entities2 = __esm(() => {
28861
29222
  });
28862
29223
 
28863
29224
  // src/cli/settings.ts
28864
- import { writeFileSync as writeFileSync17, readFileSync as readFileSync26 } from "node:fs";
29225
+ import { writeFileSync as writeFileSync18, readFileSync as readFileSync27 } from "node:fs";
28865
29226
  function handleSettingsCommand(parsed) {
28866
29227
  const ctx = requireRoot(parsed.flags);
28867
29228
  if (!ctx)
@@ -28943,7 +29304,7 @@ function handleSettingsCommand(parsed) {
28943
29304
  const out = parsed.flags.out;
28944
29305
  const json2 = exportSettings(memoryDir);
28945
29306
  if (out) {
28946
- writeFileSync17(out, json2, "utf8");
29307
+ writeFileSync18(out, json2, "utf8");
28947
29308
  console.log(`Exported settings to ${out}`);
28948
29309
  } else {
28949
29310
  console.log(json2);
@@ -28957,7 +29318,7 @@ function handleSettingsCommand(parsed) {
28957
29318
  return 2;
28958
29319
  }
28959
29320
  try {
28960
- const raw = readFileSync26(file, "utf8");
29321
+ const raw = readFileSync27(file, "utf8");
28961
29322
  importSettings(memoryDir, raw);
28962
29323
  console.log(`Successfully imported settings from ${file}`);
28963
29324
  return 0;
@@ -28980,16 +29341,16 @@ var init_nudge = __esm(() => {
28980
29341
  });
28981
29342
 
28982
29343
  // src/routines.ts
28983
- import { readFileSync as readFileSync27, existsSync as existsSync34 } from "node:fs";
28984
- import { join as join31 } from "node:path";
29344
+ import { readFileSync as readFileSync28, existsSync as existsSync36 } from "node:fs";
29345
+ import { join as join33 } from "node:path";
28985
29346
  function routinesPath(memoryDir) {
28986
- return join31(memoryDir, "routines.yaml");
29347
+ return join33(memoryDir, "routines.yaml");
28987
29348
  }
28988
29349
  function loadRoutines(memoryDir) {
28989
29350
  const p = routinesPath(memoryDir);
28990
- if (!existsSync34(p))
29351
+ if (!existsSync36(p))
28991
29352
  return { routines: {} };
28992
- const doc2 = yaml.load(readFileSync27(p, "utf8"), { schema: yaml.JSON_SCHEMA }) ?? {};
29353
+ const doc2 = yaml.load(readFileSync28(p, "utf8"), { schema: yaml.JSON_SCHEMA }) ?? {};
28993
29354
  const routines = doc2.routines ?? {};
28994
29355
  for (const [name, r] of Object.entries(routines)) {
28995
29356
  if (!r || typeof r.schedule !== "string" || !r.schedule.trim()) {
@@ -29027,7 +29388,7 @@ var init_routines = __esm(() => {
29027
29388
  });
29028
29389
 
29029
29390
  // src/cli/lifecycle.ts
29030
- import { writeFileSync as writeFileSync18, readFileSync as readFileSync28, existsSync as existsSync35 } from "node:fs";
29391
+ import { writeFileSync as writeFileSync19, readFileSync as readFileSync29, existsSync as existsSync37 } from "node:fs";
29031
29392
  async function handleProposeCommand({ positional, flags }) {
29032
29393
  const ctx = requireRoot(flags);
29033
29394
  if (!ctx)
@@ -29176,7 +29537,7 @@ async function handleExportCommand({ flags }) {
29176
29537
  const snapshot = exportSnapshot(ctx.store);
29177
29538
  const outPath = flags["out"];
29178
29539
  if (outPath) {
29179
- writeFileSync18(outPath, JSON.stringify(snapshot, null, 2), "utf8");
29540
+ writeFileSync19(outPath, JSON.stringify(snapshot, null, 2), "utf8");
29180
29541
  console.log(`exported ${snapshot.total} memories to ${outPath}`);
29181
29542
  } else {
29182
29543
  console.log(JSON.stringify(snapshot, null, 2));
@@ -29190,9 +29551,9 @@ async function handleImportCommand({ positional, flags }) {
29190
29551
  const file = positional[0];
29191
29552
  if (!file)
29192
29553
  return usageError("import requires <file.json>");
29193
- if (!existsSync35(file))
29554
+ if (!existsSync37(file))
29194
29555
  return fail(`error: file ${file} does not exist`);
29195
- const raw = JSON.parse(readFileSync28(file, "utf8"));
29556
+ const raw = JSON.parse(readFileSync29(file, "utf8"));
29196
29557
  const res = importSnapshot(ctx.store, raw, { overwrite: flags["overwrite"] === "true" });
29197
29558
  if (res.errors.length > 0) {
29198
29559
  console.error(`import encountered errors:`);
@@ -29577,6 +29938,11 @@ async function main(argv) {
29577
29938
  return handleUiCommand(parsed);
29578
29939
  case "graph":
29579
29940
  return handleGraphCommand(parsed);
29941
+ case "drift":
29942
+ case "check":
29943
+ return handleDriftCommand(parsed);
29944
+ case "compress":
29945
+ return handleCompressCommand(parsed);
29580
29946
  case "mcp":
29581
29947
  return handleMcpCommand();
29582
29948
  case "daemon":