musememory 1.6.0 → 1.6.1

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 (4) hide show
  1. package/README.md +93 -273
  2. package/dist/index.js +762 -587
  3. package/package.json +2 -1
  4. package/schema.json +60 -0
package/dist/index.js CHANGED
@@ -4,7 +4,6 @@ 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;
8
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
8
  function __accessProp(key) {
10
9
  return this[key];
@@ -33,23 +32,6 @@ var __toESM = (mod, isNodeMode, target) => {
33
32
  cache.set(mod, to);
34
33
  return to;
35
34
  };
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;
53
35
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
54
36
  var __returnValue = (v) => v;
55
37
  function __exportSetter(name, newValue) {
@@ -110,7 +92,7 @@ var init_secrets = __esm(() => {
110
92
  },
111
93
  {
112
94
  name: "Private Key Block",
113
- pattern: /-----BEGIN (?:RSA|DSA|EC|OPENSSH|PGP|ENCRYPTED|PRIVATE)? ?KEY|PRIVATE KEY/i
95
+ pattern: /-----BEGIN (?:RSA|DSA|EC|OPENSSH|PGP|ENCRYPTED|PRIVATE)? ?(?:PRIVATE )?KEY/i
114
96
  },
115
97
  {
116
98
  name: "Slack Token",
@@ -3532,7 +3514,14 @@ var init_types = __esm(() => {
3532
3514
  // src/retrieval.ts
3533
3515
  import { existsSync as existsSync4 } from "node:fs";
3534
3516
  import { join as join4 } from "node:path";
3517
+ function tokenize(text) {
3518
+ if (!text || typeof text !== "string")
3519
+ return [];
3520
+ return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
3521
+ }
3535
3522
  function stalePolicyDays(type2) {
3523
+ if (!type2)
3524
+ return DEFAULT_STALE_DAYS;
3536
3525
  switch (type2) {
3537
3526
  case "fix":
3538
3527
  return 90;
@@ -3548,11 +3537,6 @@ function stalePolicyDays(type2) {
3548
3537
  return DEFAULT_STALE_DAYS;
3549
3538
  }
3550
3539
  }
3551
- function tokenize(text) {
3552
- if (!text || typeof text !== "string")
3553
- return [];
3554
- return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
3555
- }
3556
3540
  function estimateEntryTokens(entry) {
3557
3541
  const text = `${entry.id} ${entry.status} ${entry.project} ${entry.title}
3558
3542
  ${entry.content}
@@ -3610,10 +3594,14 @@ function sortCandidates(candidates, queryTokens, now) {
3610
3594
  return candidates.map((entry) => ({ entry, score: scoreEntry(entry, queryTokens, now) })).sort((a, b) => {
3611
3595
  if (b.score !== a.score)
3612
3596
  return b.score - a.score;
3613
- const u = Date.parse(b.entry.updated_at) - Date.parse(a.entry.updated_at);
3597
+ const bU = Date.parse(b.entry.updated_at);
3598
+ const aU = Date.parse(a.entry.updated_at);
3599
+ const u = (Number.isNaN(bU) ? 0 : bU) - (Number.isNaN(aU) ? 0 : aU);
3614
3600
  if (u !== 0)
3615
3601
  return u;
3616
- return Date.parse(b.entry.created_at) - Date.parse(a.entry.created_at);
3602
+ const bC = Date.parse(b.entry.created_at);
3603
+ const aC = Date.parse(a.entry.created_at);
3604
+ return (Number.isNaN(bC) ? 0 : bC) - (Number.isNaN(aC) ? 0 : aC);
3617
3605
  });
3618
3606
  }
3619
3607
  function queryContext(store, query = "", options = {}) {
@@ -3648,14 +3636,16 @@ function queryContext(store, query = "", options = {}) {
3648
3636
  const limit = options.limit ?? 10;
3649
3637
  const results = [];
3650
3638
  let totalTokensUsed = 0;
3651
- if (options.tokenBudget && options.tokenBudget > 0) {
3652
- for (const item of scored) {
3653
- if (results.length >= limit)
3654
- break;
3655
- const tokens = estimateEntryTokens(item.entry);
3656
- if (totalTokensUsed + tokens <= options.tokenBudget) {
3657
- results.push(item);
3658
- totalTokensUsed += tokens;
3639
+ if (options.tokenBudget !== undefined) {
3640
+ if (options.tokenBudget > 0) {
3641
+ for (const item of scored) {
3642
+ if (results.length >= limit)
3643
+ break;
3644
+ const tokens = estimateEntryTokens(item.entry);
3645
+ if (totalTokensUsed + tokens <= options.tokenBudget) {
3646
+ results.push(item);
3647
+ totalTokensUsed += tokens;
3648
+ }
3659
3649
  }
3660
3650
  }
3661
3651
  } else {
@@ -3694,7 +3684,6 @@ function formatPromptContext(store, memoryDir, query = "", options = {}) {
3694
3684
  }
3695
3685
  parts.push("");
3696
3686
  }
3697
- const { getSessionHandoff } = (init_current(), __toCommonJS(exports_current));
3698
3687
  const handoff = memoryDir ? getSessionHandoff(memoryDir) : null;
3699
3688
  if (handoff && (handoff.status === "IN-PROGRESS" || handoff.task || handoff.lastQuery)) {
3700
3689
  parts.push("### Active In-Flight Context & Session Handoff (CURRENT.md)");
@@ -3721,7 +3710,6 @@ function formatPromptContext(store, memoryDir, query = "", options = {}) {
3721
3710
  }
3722
3711
  if (memoryDir && existsSync4(join4(memoryDir, "wiki"))) {
3723
3712
  try {
3724
- const { listWikiPages } = (init_wiki(), __toCommonJS(exports_wiki));
3725
3713
  const wikiPages = listWikiPages(memoryDir, { detailLevel: "l1", project: options.project });
3726
3714
  if (wikiPages.length > 0) {
3727
3715
  const queryTokens = tokenize(query);
@@ -3729,7 +3717,8 @@ function formatPromptContext(store, memoryDir, query = "", options = {}) {
3729
3717
  if (relevantWiki.length > 0) {
3730
3718
  parts.push("### Compiled Knowledge & Concepts (Wiki L1)");
3731
3719
  for (const wp of relevantWiki) {
3732
- parts.push(`- [[${wp.slug}]]: ${wp.title}${wp.summary ? ` — ${wp.summary}` : ""}`);
3720
+ const sum = wp.summary;
3721
+ parts.push(`- [[${wp.slug}]]: ${wp.title}${sum ? ` — ${sum}` : ""}`);
3733
3722
  }
3734
3723
  parts.push("");
3735
3724
  }
@@ -3792,12 +3781,190 @@ function formatPromptContext(store, memoryDir, query = "", options = {}) {
3792
3781
  userProfile
3793
3782
  };
3794
3783
  }
3784
+ var STOPWORDS;
3795
3785
  var init_retrieval = __esm(() => {
3796
3786
  init_store();
3797
- init_current();
3787
+ init_governor();
3788
+ init_compiler();
3798
3789
  init_user();
3799
3790
  init_core();
3800
3791
  init_types();
3792
+ STOPWORDS = new Set([
3793
+ "a",
3794
+ "about",
3795
+ "above",
3796
+ "after",
3797
+ "again",
3798
+ "against",
3799
+ "all",
3800
+ "am",
3801
+ "an",
3802
+ "and",
3803
+ "any",
3804
+ "are",
3805
+ "aren't",
3806
+ "as",
3807
+ "at",
3808
+ "be",
3809
+ "because",
3810
+ "been",
3811
+ "before",
3812
+ "being",
3813
+ "below",
3814
+ "between",
3815
+ "both",
3816
+ "but",
3817
+ "by",
3818
+ "can't",
3819
+ "cannot",
3820
+ "could",
3821
+ "couldn't",
3822
+ "did",
3823
+ "didn't",
3824
+ "do",
3825
+ "does",
3826
+ "doesn't",
3827
+ "doing",
3828
+ "don't",
3829
+ "down",
3830
+ "during",
3831
+ "each",
3832
+ "few",
3833
+ "for",
3834
+ "from",
3835
+ "further",
3836
+ "had",
3837
+ "hadn't",
3838
+ "has",
3839
+ "hasn't",
3840
+ "have",
3841
+ "haven't",
3842
+ "having",
3843
+ "he",
3844
+ "he'd",
3845
+ "he'll",
3846
+ "he's",
3847
+ "her",
3848
+ "here",
3849
+ "here's",
3850
+ "hers",
3851
+ "herself",
3852
+ "him",
3853
+ "himself",
3854
+ "his",
3855
+ "how",
3856
+ "how's",
3857
+ "i",
3858
+ "i'd",
3859
+ "i'll",
3860
+ "i'm",
3861
+ "i've",
3862
+ "if",
3863
+ "in",
3864
+ "into",
3865
+ "is",
3866
+ "isn't",
3867
+ "it",
3868
+ "it's",
3869
+ "its",
3870
+ "itself",
3871
+ "let's",
3872
+ "me",
3873
+ "more",
3874
+ "most",
3875
+ "mustn't",
3876
+ "my",
3877
+ "myself",
3878
+ "no",
3879
+ "nor",
3880
+ "not",
3881
+ "of",
3882
+ "off",
3883
+ "on",
3884
+ "once",
3885
+ "only",
3886
+ "or",
3887
+ "other",
3888
+ "ought",
3889
+ "our",
3890
+ "ours",
3891
+ "ourselves",
3892
+ "out",
3893
+ "over",
3894
+ "own",
3895
+ "same",
3896
+ "shan't",
3897
+ "she",
3898
+ "she'd",
3899
+ "she'll",
3900
+ "she's",
3901
+ "should",
3902
+ "shouldn't",
3903
+ "so",
3904
+ "some",
3905
+ "such",
3906
+ "than",
3907
+ "that",
3908
+ "that's",
3909
+ "the",
3910
+ "their",
3911
+ "theirs",
3912
+ "them",
3913
+ "themselves",
3914
+ "then",
3915
+ "there",
3916
+ "there's",
3917
+ "these",
3918
+ "they",
3919
+ "they'd",
3920
+ "they'll",
3921
+ "they're",
3922
+ "they've",
3923
+ "this",
3924
+ "those",
3925
+ "through",
3926
+ "to",
3927
+ "too",
3928
+ "under",
3929
+ "until",
3930
+ "up",
3931
+ "very",
3932
+ "was",
3933
+ "wasn't",
3934
+ "we",
3935
+ "we'd",
3936
+ "we'll",
3937
+ "we're",
3938
+ "we've",
3939
+ "were",
3940
+ "weren't",
3941
+ "what",
3942
+ "what's",
3943
+ "when",
3944
+ "when's",
3945
+ "where",
3946
+ "where's",
3947
+ "which",
3948
+ "while",
3949
+ "who",
3950
+ "who's",
3951
+ "whom",
3952
+ "why",
3953
+ "why's",
3954
+ "with",
3955
+ "won't",
3956
+ "would",
3957
+ "wouldn't",
3958
+ "you",
3959
+ "you'd",
3960
+ "you'll",
3961
+ "you're",
3962
+ "you've",
3963
+ "your",
3964
+ "yours",
3965
+ "yourself",
3966
+ "yourselves"
3967
+ ]);
3801
3968
  });
3802
3969
 
3803
3970
  // src/governor.ts
@@ -4062,22 +4229,6 @@ function recordSessionEnd(store, sessionId, project, summary) {
4062
4229
  save(store, entry);
4063
4230
  return entry;
4064
4231
  }
4065
- function getSessionMemories(store, sessionId) {
4066
- return list(store).filter((e) => e.session_id === sessionId && e.type !== "session");
4067
- }
4068
- function linkMemoriesToSession(store, sessionId, memoryIds) {
4069
- const updated = [];
4070
- const entries = list(store);
4071
- for (const id of memoryIds) {
4072
- const entry = entries.find((e) => e.id === id);
4073
- if (entry) {
4074
- entry.session_id = sessionId;
4075
- save(store, entry);
4076
- updated.push(entry);
4077
- }
4078
- }
4079
- return updated;
4080
- }
4081
4232
  function probeGit(workspaceRoot) {
4082
4233
  const items = [];
4083
4234
  try {
@@ -4255,266 +4406,12 @@ var init_governor = __esm(() => {
4255
4406
  });
4256
4407
 
4257
4408
  // src/current.ts
4258
- var exports_current = {};
4259
- __export(exports_current, {
4260
- WorkspaceGovernor: () => WorkspaceGovernor,
4261
- collectLoops: () => collectLoops,
4262
- collectNudges: () => collectNudges,
4263
- currentFilePath: () => currentFilePath,
4264
- dueEntries: () => dueEntries,
4265
- findSession: () => findSession,
4266
- getCurrent: () => getCurrent2,
4267
- getSessionHandoff: () => getSessionHandoff,
4268
- getSessionMemories: () => getSessionMemories,
4269
- linkMemoriesToSession: () => linkMemoriesToSession,
4270
- markSessionCompleted: () => markSessionCompleted,
4271
- parseCurrentFile: () => parseCurrentFile,
4272
- recordSessionEnd: () => recordSessionEnd,
4273
- recordSessionStart: () => recordSessionStart,
4274
- renderLoops: () => renderLoops,
4275
- renderNudges: () => renderNudges,
4276
- setCurrent: () => setCurrent,
4277
- syncConstraints: () => syncConstraints,
4278
- updateSessionHandoff: () => updateSessionHandoff,
4279
- writeCurrentFile: () => writeCurrentFile
4280
- });
4281
4409
  var init_current = __esm(() => {
4282
4410
  init_governor();
4283
4411
  });
4284
4412
 
4285
- // src/sqlite.ts
4286
- import { existsSync as existsSync6, mkdirSync as mkdirSync5 } from "node:fs";
4287
- import { dirname } from "node:path";
4288
- function getDriver() {
4289
- if (sqliteDriver !== "none")
4290
- return sqliteDriver;
4291
- try {
4292
- if (typeof globalThis.Bun !== "undefined") {
4293
- sqliteDriver = "bun";
4294
- return "bun";
4295
- }
4296
- } catch {}
4297
- try {
4298
- __require("node:sqlite");
4299
- sqliteDriver = "node";
4300
- return "node";
4301
- } catch {}
4302
- sqliteDriver = "bun";
4303
- return "bun";
4304
- }
4305
- function openDatabase(dbPath) {
4306
- const dir = dirname(dbPath);
4307
- if (!existsSync6(dir)) {
4308
- mkdirSync5(dir, { recursive: true });
4309
- }
4310
- const driver = getDriver();
4311
- let rawDb;
4312
- if (driver === "bun") {
4313
- const { Database } = __require("bun:sqlite");
4314
- rawDb = new Database(dbPath, { create: true });
4315
- rawDb.run("PRAGMA journal_mode = WAL;");
4316
- rawDb.run("PRAGMA synchronous = NORMAL;");
4317
- const db = {
4318
- exec(sql) {
4319
- rawDb.exec(sql);
4320
- },
4321
- run(sql, params) {
4322
- if (params && Array.isArray(params)) {
4323
- rawDb.run(sql, params);
4324
- } else if (params && typeof params === "object") {
4325
- rawDb.run(sql, params);
4326
- } else {
4327
- rawDb.run(sql);
4328
- }
4329
- },
4330
- query(sql) {
4331
- const stmt = rawDb.query(sql);
4332
- return {
4333
- all(params) {
4334
- return params ? stmt.all(params) : stmt.all();
4335
- },
4336
- get(params) {
4337
- return params ? stmt.get(params) : stmt.get();
4338
- }
4339
- };
4340
- },
4341
- close() {
4342
- rawDb.close();
4343
- }
4344
- };
4345
- initSchema(db);
4346
- return db;
4347
- } else {
4348
- const { DatabaseSync } = __require("node:sqlite");
4349
- rawDb = new DatabaseSync(dbPath);
4350
- rawDb.exec("PRAGMA journal_mode = WAL;");
4351
- rawDb.exec("PRAGMA synchronous = NORMAL;");
4352
- const db = {
4353
- exec(sql) {
4354
- rawDb.exec(sql);
4355
- },
4356
- run(sql, params) {
4357
- const stmt = rawDb.prepare(sql);
4358
- if (params && Array.isArray(params)) {
4359
- stmt.run(...params);
4360
- } else if (params && typeof params === "object") {
4361
- stmt.run(params);
4362
- } else {
4363
- stmt.run();
4364
- }
4365
- },
4366
- query(sql) {
4367
- const stmt = rawDb.prepare(sql);
4368
- return {
4369
- all(params) {
4370
- if (params && Array.isArray(params))
4371
- return stmt.all(...params);
4372
- if (params && typeof params === "object")
4373
- return stmt.all(params);
4374
- return stmt.all();
4375
- },
4376
- get(params) {
4377
- if (params && Array.isArray(params))
4378
- return stmt.get(...params);
4379
- if (params && typeof params === "object")
4380
- return stmt.get(params);
4381
- return stmt.get();
4382
- }
4383
- };
4384
- },
4385
- close() {
4386
- rawDb.close();
4387
- }
4388
- };
4389
- initSchema(db);
4390
- return db;
4391
- }
4392
- }
4393
- function initSchema(db) {
4394
- db.exec(`
4395
- CREATE TABLE IF NOT EXISTS memories (
4396
- id TEXT PRIMARY KEY,
4397
- title TEXT NOT NULL,
4398
- content TEXT NOT NULL,
4399
- project TEXT NOT NULL,
4400
- type TEXT NOT NULL,
4401
- status TEXT NOT NULL,
4402
- salience REAL,
4403
- reinforcement INTEGER,
4404
- session_id TEXT,
4405
- due_at TEXT,
4406
- expires_at TEXT,
4407
- valid_from TEXT,
4408
- valid_to TEXT,
4409
- data TEXT NOT NULL,
4410
- created_at TEXT NOT NULL,
4411
- updated_at TEXT NOT NULL
4412
- );
4413
-
4414
- CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project);
4415
- CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
4416
- CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
4417
- CREATE INDEX IF NOT EXISTS idx_memories_session_id ON memories(session_id);
4418
- CREATE INDEX IF NOT EXISTS idx_memories_due_at ON memories(due_at);
4419
- CREATE INDEX IF NOT EXISTS idx_memories_updated_at ON memories(updated_at);
4420
- `);
4421
- }
4422
- function rowToMemoryEntry(row) {
4423
- let parsedData = {};
4424
- try {
4425
- parsedData = JSON.parse(row.data);
4426
- } catch {}
4427
- return {
4428
- ...parsedData,
4429
- id: row.id,
4430
- title: row.title,
4431
- content: row.content,
4432
- project: row.project,
4433
- type: row.type,
4434
- status: row.status,
4435
- salience: row.salience !== null ? row.salience : parsedData.salience,
4436
- reinforcement: row.reinforcement !== null ? row.reinforcement : parsedData.reinforcement,
4437
- session_id: row.session_id !== null ? row.session_id : parsedData.session_id,
4438
- due_at: row.due_at !== null ? row.due_at : parsedData.due_at,
4439
- expires_at: row.expires_at !== null ? row.expires_at : parsedData.expires_at,
4440
- valid_from: row.valid_from !== null ? row.valid_from : parsedData.valid_from,
4441
- valid_to: row.valid_to !== null ? row.valid_to : parsedData.valid_to,
4442
- created_at: row.created_at || parsedData.created_at || new Date().toISOString(),
4443
- updated_at: row.updated_at || parsedData.updated_at || new Date().toISOString()
4444
- };
4445
- }
4446
- function insertOrReplaceMemory(db, entry) {
4447
- const sql = `
4448
- INSERT OR REPLACE INTO memories (
4449
- id, title, content, project, type, status, salience, reinforcement,
4450
- session_id, due_at, expires_at, valid_from, valid_to, data,
4451
- created_at, updated_at
4452
- ) VALUES (
4453
- ?, ?, ?, ?, ?, ?, ?, ?,
4454
- ?, ?, ?, ?, ?, ?,
4455
- ?, ?
4456
- )
4457
- `;
4458
- db.run(sql, [
4459
- entry.id,
4460
- entry.title,
4461
- entry.content,
4462
- entry.project,
4463
- entry.type || "discovery",
4464
- entry.status,
4465
- typeof entry.salience === "number" ? entry.salience : null,
4466
- typeof entry.reinforcement === "number" ? entry.reinforcement : null,
4467
- entry.session_id ?? null,
4468
- entry.due_at ?? null,
4469
- entry.expires_at ?? null,
4470
- entry.valid_from ?? null,
4471
- entry.valid_to ?? null,
4472
- JSON.stringify(entry),
4473
- entry.created_at,
4474
- entry.updated_at
4475
- ]);
4476
- }
4477
- function getMemoryById(db, id) {
4478
- const row = db.query(`SELECT * FROM memories WHERE id = ? LIMIT 1`).get([id]);
4479
- if (!row)
4480
- return null;
4481
- return rowToMemoryEntry(row);
4482
- }
4483
- function listMemories(db, filters) {
4484
- let sql = `SELECT * FROM memories`;
4485
- const conditions = [];
4486
- const params = [];
4487
- if (filters?.project) {
4488
- conditions.push(`project = ?`);
4489
- params.push(filters.project);
4490
- }
4491
- if (filters?.type) {
4492
- conditions.push(`type = ?`);
4493
- params.push(filters.type);
4494
- }
4495
- if (filters?.status) {
4496
- conditions.push(`status = ?`);
4497
- params.push(filters.status);
4498
- }
4499
- if (conditions.length > 0) {
4500
- sql += ` WHERE ` + conditions.join(` AND `);
4501
- }
4502
- sql += ` ORDER BY updated_at DESC`;
4503
- const rows = db.query(sql).all(params.length > 0 ? params : undefined);
4504
- return rows.map(rowToMemoryEntry);
4505
- }
4506
- function deleteMemoryById(db, id) {
4507
- const existing = getMemoryById(db, id);
4508
- if (!existing)
4509
- return false;
4510
- db.run(`DELETE FROM memories WHERE id = ?`, [id]);
4511
- return true;
4512
- }
4513
- var sqliteDriver = "none";
4514
- var init_sqlite = () => {};
4515
-
4516
4413
  // src/transcript.ts
4517
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "node:fs";
4414
+ import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
4518
4415
  function parseJsonlTranscript(jsonlText) {
4519
4416
  if (!jsonlText)
4520
4417
  return [];
@@ -4565,7 +4462,7 @@ function parseJsonlTranscript(jsonlText) {
4565
4462
  }
4566
4463
  function searchTranscriptWithBookends(transcriptPathOrContent, query, options = {}) {
4567
4464
  let content = transcriptPathOrContent;
4568
- if (existsSync7(transcriptPathOrContent)) {
4465
+ if (existsSync6(transcriptPathOrContent)) {
4569
4466
  content = readFileSync5(transcriptPathOrContent, "utf8");
4570
4467
  }
4571
4468
  const turns = parseJsonlTranscript(content);
@@ -4636,15 +4533,7 @@ ${m.matchedTurn}`);
4636
4533
  var init_transcript = () => {};
4637
4534
 
4638
4535
  // src/harvest.ts
4639
- var exports_harvest = {};
4640
- __export(exports_harvest, {
4641
- defaultSalienceForType: () => defaultSalienceForType,
4642
- extractCommitments: () => extractCommitments,
4643
- extractHarvestUnits: () => extractHarvestUnits,
4644
- importTranscript: () => importTranscript,
4645
- openLoopId: () => openLoopId
4646
- });
4647
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "node:fs";
4536
+ import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
4648
4537
  import { createHash } from "node:crypto";
4649
4538
  function extractHarvestUnits(text) {
4650
4539
  if (!text || typeof text !== "string")
@@ -4769,96 +4658,328 @@ function extractCommitments(text) {
4769
4658
  }
4770
4659
  break;
4771
4660
  }
4772
- }
4661
+ }
4662
+ }
4663
+ return out;
4664
+ }
4665
+ function openLoopId(text) {
4666
+ const h = createHash("sha256").update(text.toLowerCase().replace(/\s+/g, " ").trim()).digest("hex");
4667
+ return `m_0_ol${h.slice(0, 12)}`;
4668
+ }
4669
+ function importTranscript(store, transcriptPathOrContent, options = {}) {
4670
+ let content = transcriptPathOrContent;
4671
+ if (existsSync7(transcriptPathOrContent)) {
4672
+ content = readFileSync6(transcriptPathOrContent, "utf8");
4673
+ }
4674
+ const blocks = parseJsonlTranscript(content);
4675
+ const fullText = blocks.join(`
4676
+
4677
+ `);
4678
+ const units = extractHarvestUnits(fullText);
4679
+ const project = options.project ?? "default";
4680
+ const entries = [];
4681
+ const errors = [];
4682
+ for (const unit of units) {
4683
+ try {
4684
+ const entry = propose(store, {
4685
+ project,
4686
+ title: unit.title,
4687
+ content: unit.content,
4688
+ type: unit.type,
4689
+ tags: unit.tags,
4690
+ source: options.source ?? "transcript_import",
4691
+ confirmed: options.confirmed ?? false
4692
+ });
4693
+ if (options.sessionId) {
4694
+ entry.session_id = options.sessionId;
4695
+ save(store, entry);
4696
+ }
4697
+ entries.push(entry);
4698
+ } catch (err) {
4699
+ errors.push(`Failed to import unit "${unit.title}": ${err instanceof Error ? err.message : String(err)}`);
4700
+ }
4701
+ }
4702
+ const openLoops = [];
4703
+ if (options.openLoops !== false) {
4704
+ const existing = new Set(list(store).map((e) => e.id));
4705
+ for (const commitment of extractCommitments(fullText)) {
4706
+ const id = openLoopId(commitment);
4707
+ if (existing.has(id))
4708
+ continue;
4709
+ try {
4710
+ const entry = propose(store, {
4711
+ id,
4712
+ project,
4713
+ title: commitment.slice(0, 80),
4714
+ content: commitment,
4715
+ type: "operation",
4716
+ tags: ["open-loop", "harvested"],
4717
+ source: options.source ?? "transcript_import"
4718
+ });
4719
+ if (options.sessionId) {
4720
+ entry.session_id = options.sessionId;
4721
+ save(store, entry);
4722
+ }
4723
+ existing.add(id);
4724
+ openLoops.push(entry);
4725
+ } catch (err) {
4726
+ errors.push(`Failed to record open loop "${commitment}": ${err instanceof Error ? err.message : String(err)}`);
4727
+ }
4728
+ }
4729
+ }
4730
+ return {
4731
+ imported: entries.length,
4732
+ entries,
4733
+ errors,
4734
+ openLoops
4735
+ };
4736
+ }
4737
+ var COMMITMENT_PATTERNS;
4738
+ var init_harvest = __esm(() => {
4739
+ init_store();
4740
+ init_transcript();
4741
+ COMMITMENT_PATTERNS = [
4742
+ /\btodo\b\s*[:\-]\s*(.{4,})/i,
4743
+ /\b(?:i'll|i will|i am going to)\s+(.{4,})/i,
4744
+ /\bneed to\s+(.{4,})/i,
4745
+ /\bfollow up (?:on|with)\s+(.{4,})/i,
4746
+ /\bremind me to\s+(.{4,})/i
4747
+ ];
4748
+ });
4749
+
4750
+ // src/sqlite.ts
4751
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5 } from "node:fs";
4752
+ import { dirname } from "node:path";
4753
+ function getDriver() {
4754
+ if (sqliteDriver !== "none")
4755
+ return sqliteDriver;
4756
+ try {
4757
+ if (typeof globalThis.Bun !== "undefined") {
4758
+ sqliteDriver = "bun";
4759
+ return "bun";
4760
+ }
4761
+ } catch {}
4762
+ try {
4763
+ __require("node:sqlite");
4764
+ sqliteDriver = "node";
4765
+ return "node";
4766
+ } catch {}
4767
+ sqliteDriver = "bun";
4768
+ return "bun";
4769
+ }
4770
+ function openDatabase(dbPath) {
4771
+ const dir = dirname(dbPath);
4772
+ if (!existsSync8(dir)) {
4773
+ mkdirSync5(dir, { recursive: true });
4774
+ }
4775
+ const driver = getDriver();
4776
+ let rawDb;
4777
+ if (driver === "bun") {
4778
+ const { Database } = __require("bun:sqlite");
4779
+ rawDb = new Database(dbPath, { create: true });
4780
+ rawDb.run("PRAGMA journal_mode = WAL;");
4781
+ rawDb.run("PRAGMA synchronous = NORMAL;");
4782
+ const db = {
4783
+ exec(sql) {
4784
+ rawDb.exec(sql);
4785
+ },
4786
+ run(sql, params) {
4787
+ if (params && Array.isArray(params)) {
4788
+ rawDb.run(sql, params);
4789
+ } else if (params && typeof params === "object") {
4790
+ rawDb.run(sql, params);
4791
+ } else {
4792
+ rawDb.run(sql);
4793
+ }
4794
+ },
4795
+ query(sql) {
4796
+ const stmt = rawDb.query(sql);
4797
+ return {
4798
+ all(params) {
4799
+ return params ? stmt.all(params) : stmt.all();
4800
+ },
4801
+ get(params) {
4802
+ return params ? stmt.get(params) : stmt.get();
4803
+ }
4804
+ };
4805
+ },
4806
+ close() {
4807
+ rawDb.close();
4808
+ }
4809
+ };
4810
+ initSchema(db);
4811
+ return db;
4812
+ } else {
4813
+ const { DatabaseSync } = __require("node:sqlite");
4814
+ rawDb = new DatabaseSync(dbPath);
4815
+ rawDb.exec("PRAGMA journal_mode = WAL;");
4816
+ rawDb.exec("PRAGMA synchronous = NORMAL;");
4817
+ const db = {
4818
+ exec(sql) {
4819
+ rawDb.exec(sql);
4820
+ },
4821
+ run(sql, params) {
4822
+ const stmt = rawDb.prepare(sql);
4823
+ if (params && Array.isArray(params)) {
4824
+ stmt.run(...params);
4825
+ } else if (params && typeof params === "object") {
4826
+ stmt.run(params);
4827
+ } else {
4828
+ stmt.run();
4829
+ }
4830
+ },
4831
+ query(sql) {
4832
+ const stmt = rawDb.prepare(sql);
4833
+ return {
4834
+ all(params) {
4835
+ if (params && Array.isArray(params))
4836
+ return stmt.all(...params);
4837
+ if (params && typeof params === "object")
4838
+ return stmt.all(params);
4839
+ return stmt.all();
4840
+ },
4841
+ get(params) {
4842
+ if (params && Array.isArray(params))
4843
+ return stmt.get(...params);
4844
+ if (params && typeof params === "object")
4845
+ return stmt.get(params);
4846
+ return stmt.get();
4847
+ }
4848
+ };
4849
+ },
4850
+ close() {
4851
+ rawDb.close();
4852
+ }
4853
+ };
4854
+ initSchema(db);
4855
+ return db;
4773
4856
  }
4774
- return out;
4775
4857
  }
4776
- function openLoopId(text) {
4777
- const h = createHash("sha256").update(text.toLowerCase().replace(/\s+/g, " ").trim()).digest("hex");
4778
- return `m_0_ol${h.slice(0, 12)}`;
4858
+ function initSchema(db) {
4859
+ db.exec(`
4860
+ CREATE TABLE IF NOT EXISTS memories (
4861
+ id TEXT PRIMARY KEY,
4862
+ title TEXT NOT NULL,
4863
+ content TEXT NOT NULL,
4864
+ project TEXT NOT NULL,
4865
+ type TEXT NOT NULL,
4866
+ status TEXT NOT NULL,
4867
+ salience REAL,
4868
+ reinforcement INTEGER,
4869
+ session_id TEXT,
4870
+ due_at TEXT,
4871
+ expires_at TEXT,
4872
+ valid_from TEXT,
4873
+ valid_to TEXT,
4874
+ data TEXT NOT NULL,
4875
+ created_at TEXT NOT NULL,
4876
+ updated_at TEXT NOT NULL
4877
+ );
4878
+
4879
+ CREATE INDEX IF NOT EXISTS idx_memories_project ON memories(project);
4880
+ CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(type);
4881
+ CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status);
4882
+ CREATE INDEX IF NOT EXISTS idx_memories_session_id ON memories(session_id);
4883
+ CREATE INDEX IF NOT EXISTS idx_memories_due_at ON memories(due_at);
4884
+ CREATE INDEX IF NOT EXISTS idx_memories_updated_at ON memories(updated_at);
4885
+ `);
4779
4886
  }
4780
- function importTranscript(store, transcriptPathOrContent, options = {}) {
4781
- let content = transcriptPathOrContent;
4782
- if (existsSync8(transcriptPathOrContent)) {
4783
- content = readFileSync6(transcriptPathOrContent, "utf8");
4887
+ function rowToMemoryEntry(row) {
4888
+ let parsedData = {};
4889
+ try {
4890
+ parsedData = JSON.parse(row.data);
4891
+ } catch {}
4892
+ return {
4893
+ ...parsedData,
4894
+ id: row.id,
4895
+ title: row.title,
4896
+ content: row.content,
4897
+ project: row.project,
4898
+ type: row.type,
4899
+ status: row.status,
4900
+ salience: row.salience !== null ? row.salience : parsedData.salience,
4901
+ reinforcement: row.reinforcement !== null ? row.reinforcement : parsedData.reinforcement,
4902
+ session_id: row.session_id !== null ? row.session_id : parsedData.session_id,
4903
+ due_at: row.due_at !== null ? row.due_at : parsedData.due_at,
4904
+ expires_at: row.expires_at !== null ? row.expires_at : parsedData.expires_at,
4905
+ valid_from: row.valid_from !== null ? row.valid_from : parsedData.valid_from,
4906
+ valid_to: row.valid_to !== null ? row.valid_to : parsedData.valid_to,
4907
+ created_at: row.created_at || parsedData.created_at || new Date().toISOString(),
4908
+ updated_at: row.updated_at || parsedData.updated_at || new Date().toISOString()
4909
+ };
4910
+ }
4911
+ function insertOrReplaceMemory(db, entry) {
4912
+ const sql = `
4913
+ INSERT OR REPLACE INTO memories (
4914
+ id, title, content, project, type, status, salience, reinforcement,
4915
+ session_id, due_at, expires_at, valid_from, valid_to, data,
4916
+ created_at, updated_at
4917
+ ) VALUES (
4918
+ ?, ?, ?, ?, ?, ?, ?, ?,
4919
+ ?, ?, ?, ?, ?, ?,
4920
+ ?, ?
4921
+ )
4922
+ `;
4923
+ db.run(sql, [
4924
+ entry.id,
4925
+ entry.title,
4926
+ entry.content,
4927
+ entry.project,
4928
+ entry.type || "discovery",
4929
+ entry.status,
4930
+ typeof entry.salience === "number" ? entry.salience : null,
4931
+ typeof entry.reinforcement === "number" ? entry.reinforcement : null,
4932
+ entry.session_id ?? null,
4933
+ entry.due_at ?? null,
4934
+ entry.expires_at ?? null,
4935
+ entry.valid_from ?? null,
4936
+ entry.valid_to ?? null,
4937
+ JSON.stringify(entry),
4938
+ entry.created_at,
4939
+ entry.updated_at
4940
+ ]);
4941
+ }
4942
+ function getMemoryById(db, id) {
4943
+ const row = db.query(`SELECT * FROM memories WHERE id = ? LIMIT 1`).get([id]);
4944
+ if (!row)
4945
+ return null;
4946
+ return rowToMemoryEntry(row);
4947
+ }
4948
+ function listMemories(db, filters) {
4949
+ let sql = `SELECT * FROM memories`;
4950
+ const conditions = [];
4951
+ const params = [];
4952
+ if (filters?.project) {
4953
+ conditions.push(`project = ?`);
4954
+ params.push(filters.project);
4784
4955
  }
4785
- const blocks = parseJsonlTranscript(content);
4786
- const fullText = blocks.join(`
4787
-
4788
- `);
4789
- const units = extractHarvestUnits(fullText);
4790
- const project = options.project ?? "default";
4791
- const entries = [];
4792
- const errors = [];
4793
- for (const unit of units) {
4794
- try {
4795
- const entry = propose(store, {
4796
- project,
4797
- title: unit.title,
4798
- content: unit.content,
4799
- type: unit.type,
4800
- tags: unit.tags,
4801
- source: options.source ?? "transcript_import",
4802
- confirmed: options.confirmed ?? false
4803
- });
4804
- if (options.sessionId) {
4805
- entry.session_id = options.sessionId;
4806
- save(store, entry);
4807
- }
4808
- entries.push(entry);
4809
- } catch (err) {
4810
- errors.push(`Failed to import unit "${unit.title}": ${err instanceof Error ? err.message : String(err)}`);
4811
- }
4956
+ if (filters?.type) {
4957
+ conditions.push(`type = ?`);
4958
+ params.push(filters.type);
4812
4959
  }
4813
- const openLoops = [];
4814
- if (options.openLoops !== false) {
4815
- const existing = new Set(list(store).map((e) => e.id));
4816
- for (const commitment of extractCommitments(fullText)) {
4817
- const id = openLoopId(commitment);
4818
- if (existing.has(id))
4819
- continue;
4820
- try {
4821
- const entry = propose(store, {
4822
- id,
4823
- project,
4824
- title: commitment.slice(0, 80),
4825
- content: commitment,
4826
- type: "operation",
4827
- tags: ["open-loop", "harvested"],
4828
- source: options.source ?? "transcript_import"
4829
- });
4830
- if (options.sessionId) {
4831
- entry.session_id = options.sessionId;
4832
- save(store, entry);
4833
- }
4834
- existing.add(id);
4835
- openLoops.push(entry);
4836
- } catch (err) {
4837
- errors.push(`Failed to record open loop "${commitment}": ${err instanceof Error ? err.message : String(err)}`);
4838
- }
4839
- }
4960
+ if (filters?.status) {
4961
+ conditions.push(`status = ?`);
4962
+ params.push(filters.status);
4840
4963
  }
4841
- return {
4842
- imported: entries.length,
4843
- entries,
4844
- errors,
4845
- openLoops
4846
- };
4964
+ if (conditions.length > 0) {
4965
+ sql += ` WHERE ` + conditions.join(` AND `);
4966
+ }
4967
+ sql += ` ORDER BY updated_at DESC`;
4968
+ const rows = db.query(sql).all(params.length > 0 ? params : undefined);
4969
+ return rows.map(rowToMemoryEntry);
4847
4970
  }
4848
- var COMMITMENT_PATTERNS;
4849
- var init_harvest = __esm(() => {
4850
- init_store();
4851
- init_transcript();
4852
- COMMITMENT_PATTERNS = [
4853
- /\btodo\b\s*[:\-]\s*(.{4,})/i,
4854
- /\b(?:i'll|i will|i am going to)\s+(.{4,})/i,
4855
- /\bneed to\s+(.{4,})/i,
4856
- /\bfollow up (?:on|with)\s+(.{4,})/i,
4857
- /\bremind me to\s+(.{4,})/i
4858
- ];
4859
- });
4971
+ function deleteMemoryById(db, id) {
4972
+ const existing = getMemoryById(db, id);
4973
+ if (!existing)
4974
+ return false;
4975
+ db.run(`DELETE FROM memories WHERE id = ?`, [id]);
4976
+ return true;
4977
+ }
4978
+ var sqliteDriver = "none";
4979
+ var init_sqlite = () => {};
4860
4980
 
4861
4981
  // src/store.ts
4982
+ import { resolve } from "node:path";
4862
4983
  import { readdirSync, readFileSync as readFileSync7, writeFileSync as writeFileSync4, renameSync, unlinkSync, mkdirSync as mkdirSync6, existsSync as existsSync9 } from "node:fs";
4863
4984
  import { join as join6 } from "node:path";
4864
4985
  function getStorageLayout(memoryDir) {
@@ -4898,7 +5019,6 @@ function openStore(memoryDir) {
4898
5019
  syncConstraints(memoryDir, store);
4899
5020
  } catch {}
4900
5021
  try {
4901
- const { autoCompileWiki } = (init_wiki(), __toCommonJS(exports_wiki));
4902
5022
  autoCompileWiki(store, memoryDir);
4903
5023
  } catch {}
4904
5024
  return store;
@@ -4919,7 +5039,13 @@ function slugifyId(id) {
4919
5039
  return slug.length > 0 ? slug : "entry";
4920
5040
  }
4921
5041
  function fileForId(store, id) {
4922
- return join6(store.dir, `${slugifyId(id)}.yaml`);
5042
+ const safeFilename = `${slugifyId(id)}.yaml`;
5043
+ const target = resolve(store.dir, safeFilename);
5044
+ const base = resolve(store.dir);
5045
+ if (!target.startsWith(base)) {
5046
+ throw new Error(`Security Violation: Path traversal detected for id "${id}"`);
5047
+ }
5048
+ return target;
4923
5049
  }
4924
5050
  function listIds(store) {
4925
5051
  const ids = new Set;
@@ -5290,8 +5416,7 @@ function deleteEntry(store, id, reason, actor) {
5290
5416
  return deleted;
5291
5417
  }
5292
5418
  function harvestMemories(store, params) {
5293
- const { extractHarvestUnits: extractHarvestUnits2 } = (init_harvest(), __toCommonJS(exports_harvest));
5294
- const units = extractHarvestUnits2(params.text);
5419
+ const units = extractHarvestUnits(params.text);
5295
5420
  const created = [];
5296
5421
  for (const u of units) {
5297
5422
  try {
@@ -5313,6 +5438,8 @@ var init_store = __esm(() => {
5313
5438
  init_secrets();
5314
5439
  init_audit();
5315
5440
  init_current();
5441
+ init_compiler();
5442
+ init_harvest();
5316
5443
  init_root();
5317
5444
  init_sqlite();
5318
5445
  });
@@ -5640,7 +5767,15 @@ function loadEntities(memoryDir) {
5640
5767
  function findEntity(memoryDir, id) {
5641
5768
  const entities = loadEntities(memoryDir);
5642
5769
  const cleanId = slugify(id);
5643
- return entities.find((e) => e.id === cleanId || e.name.toLowerCase() === id.toLowerCase()) ?? null;
5770
+ const alphanumericId = id.toLowerCase().replace(/[^a-z0-9]/g, "");
5771
+ return entities.find((e) => {
5772
+ if (e.id === cleanId || e.name.toLowerCase() === id.toLowerCase())
5773
+ return true;
5774
+ if (slugify(e.name) === cleanId)
5775
+ return true;
5776
+ const alphaE = e.id.toLowerCase().replace(/[^a-z0-9]/g, "");
5777
+ return alphaE.length > 0 && alphaE === alphanumericId;
5778
+ }) ?? null;
5644
5779
  }
5645
5780
  function findRelatedEntities(memoryDir, id) {
5646
5781
  const entities = loadEntities(memoryDir);
@@ -6101,6 +6236,12 @@ function buildLogPage(logEntries) {
6101
6236
  entries: logEntries
6102
6237
  };
6103
6238
  }
6239
+ function stripFrontmatter(content) {
6240
+ const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);
6241
+ if (!match)
6242
+ return content;
6243
+ return content.slice(match[0].length);
6244
+ }
6104
6245
  function loadExistingConcepts(dir) {
6105
6246
  const map2 = new Map;
6106
6247
  if (!existsSync11(dir))
@@ -6112,9 +6253,7 @@ function loadExistingConcepts(dir) {
6112
6253
  try {
6113
6254
  const content = readFileSync9(join8(dir, file), "utf8");
6114
6255
  const frontmatter = parseFrontmatter(content);
6115
- map2.set(slug, { ...frontmatter, slug, content: content.slice(content.indexOf(`
6116
- ---
6117
- `) + 5) });
6256
+ map2.set(slug, { ...frontmatter, slug, content: stripFrontmatter(content) });
6118
6257
  } catch {}
6119
6258
  }
6120
6259
  return map2;
@@ -6130,26 +6269,41 @@ function loadExistingEntities(dir) {
6130
6269
  try {
6131
6270
  const content = readFileSync9(join8(dir, file), "utf8");
6132
6271
  const frontmatter = parseFrontmatter(content);
6133
- map2.set(slug, { ...frontmatter, slug, content: content.slice(content.indexOf(`
6134
- ---
6135
- `) + 5) });
6272
+ map2.set(slug, { ...frontmatter, slug, content: stripFrontmatter(content) });
6136
6273
  } catch {}
6137
6274
  }
6138
6275
  return map2;
6139
6276
  }
6140
6277
  function parseFrontmatter(content) {
6141
- const match = content.match(/^---\n([\s\S]*?)\n---/);
6278
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
6142
6279
  if (!match)
6143
6280
  return {};
6144
- const lines = match[1].split(`
6145
- `);
6281
+ const lines = match[1].split(/\r?\n/);
6146
6282
  const obj = {};
6147
6283
  for (const line of lines) {
6148
6284
  const idx = line.indexOf(":");
6149
6285
  if (idx > 0) {
6150
6286
  const key = line.slice(0, idx).trim();
6151
- const value = line.slice(idx + 1).trim();
6152
- obj[key] = value.replace(/^["']|["']$/g, "");
6287
+ const rawVal = line.slice(idx + 1).trim();
6288
+ if (rawVal.startsWith("[") && rawVal.endsWith("]")) {
6289
+ try {
6290
+ obj[key] = JSON.parse(rawVal);
6291
+ continue;
6292
+ } catch {}
6293
+ }
6294
+ if (rawVal === "true") {
6295
+ obj[key] = true;
6296
+ continue;
6297
+ }
6298
+ if (rawVal === "false") {
6299
+ obj[key] = false;
6300
+ continue;
6301
+ }
6302
+ if (!isNaN(Number(rawVal)) && rawVal !== "") {
6303
+ obj[key] = Number(rawVal);
6304
+ continue;
6305
+ }
6306
+ obj[key] = rawVal.replace(/^["']|["']$/g, "");
6153
6307
  }
6154
6308
  }
6155
6309
  return obj;
@@ -6306,18 +6460,6 @@ var init_compiler = __esm(() => {
6306
6460
  });
6307
6461
 
6308
6462
  // src/wiki/index.ts
6309
- var exports_wiki = {};
6310
- __export(exports_wiki, {
6311
- autoCompileWiki: () => autoCompileWiki,
6312
- compileWiki: () => compileWiki,
6313
- ensureWikiStructure: () => ensureWikiStructure,
6314
- getWikiPage: () => getWikiPage,
6315
- listWikiPages: () => listWikiPages,
6316
- renderConceptPage: () => renderConceptPage,
6317
- renderEntityPage: () => renderEntityPage,
6318
- renderIndexPage: () => renderIndexPage,
6319
- renderLogPage: () => renderLogPage
6320
- });
6321
6463
  var init_wiki = __esm(() => {
6322
6464
  init_compiler();
6323
6465
  });
@@ -6454,7 +6596,8 @@ function parseFlags(args) {
6454
6596
  }
6455
6597
  function requireRoot(flags = {}) {
6456
6598
  const isGlobal = flags["global"] === "true";
6457
- const { root, memoryDir } = findOrCreateProjectRoot(process.cwd(), { global: isGlobal });
6599
+ const startDir = flags["dir"] || process.cwd();
6600
+ const { root, memoryDir } = findOrCreateProjectRoot(startDir, { global: isGlobal });
6458
6601
  return { root, memoryDir, store: openStore(memoryDir) };
6459
6602
  }
6460
6603
  function usageError(msg) {
@@ -6515,7 +6658,7 @@ function normalizeMemoryType(raw) {
6515
6658
 
6516
6659
  // src/migrator/detect.ts
6517
6660
  import { existsSync as existsSync13 } from "node:fs";
6518
- import { join as join10, resolve } from "node:path";
6661
+ import { join as join10, resolve as resolve2 } from "node:path";
6519
6662
  import { homedir as homedir2 } from "node:os";
6520
6663
  function expandPath(p, baseDir) {
6521
6664
  if (p.startsWith("~/") || p === "~") {
@@ -6524,7 +6667,7 @@ function expandPath(p, baseDir) {
6524
6667
  if (p.startsWith("/")) {
6525
6668
  return p;
6526
6669
  }
6527
- return resolve(baseDir, p);
6670
+ return resolve2(baseDir, p);
6528
6671
  }
6529
6672
  function detectProviders(baseDir = process.cwd()) {
6530
6673
  return PROVIDER_DEFINITIONS.map((def) => {
@@ -7402,14 +7545,14 @@ ${title}`);
7402
7545
  input: process.stdin,
7403
7546
  output: process.stdout
7404
7547
  });
7405
- return new Promise((resolve2) => {
7548
+ return new Promise((resolve3) => {
7406
7549
  rl.question(`Enter selection (e.g. "1,3" or "all") [default: ${defaultAll ? "all" : "none"}]: `, (answer) => {
7407
7550
  rl.close();
7408
7551
  const result = parseSelectionInput(answer, options, defaultAll);
7409
7552
  if (answer.trim().toLowerCase().startsWith("q")) {
7410
7553
  console.log("Operation cancelled.");
7411
7554
  }
7412
- resolve2(result);
7555
+ resolve3(result);
7413
7556
  });
7414
7557
  });
7415
7558
  }
@@ -7432,23 +7575,23 @@ ${title}`);
7432
7575
  input: process.stdin,
7433
7576
  output: process.stdout
7434
7577
  });
7435
- return new Promise((resolve2) => {
7578
+ return new Promise((resolve3) => {
7436
7579
  rl.question(`
7437
7580
  Select role archetype [1-${options.length}] (default: 1): `, (answer) => {
7438
7581
  rl.close();
7439
7582
  const trimmed = answer.trim();
7440
7583
  if (!trimmed) {
7441
- return resolve2(defaultId);
7584
+ return resolve3(defaultId);
7442
7585
  }
7443
7586
  const num = parseInt(trimmed, 10);
7444
7587
  if (!isNaN(num) && num >= 1 && num <= options.length) {
7445
- return resolve2(options[num - 1].id);
7588
+ return resolve3(options[num - 1].id);
7446
7589
  }
7447
7590
  const matched = options.find((o) => o.id.toLowerCase() === trimmed.toLowerCase() || o.label.toLowerCase().includes(trimmed.toLowerCase()));
7448
7591
  if (matched) {
7449
- return resolve2(matched.id);
7592
+ return resolve3(matched.id);
7450
7593
  }
7451
- resolve2(defaultId);
7594
+ resolve3(defaultId);
7452
7595
  });
7453
7596
  });
7454
7597
  }
@@ -11524,7 +11667,7 @@ var require_compile = __commonJS(function(exports) {
11524
11667
  const schOrFunc = root.refs[ref];
11525
11668
  if (schOrFunc)
11526
11669
  return schOrFunc;
11527
- let _sch = resolve2.call(this, root, ref);
11670
+ let _sch = resolve3.call(this, root, ref);
11528
11671
  if (_sch === undefined) {
11529
11672
  const schema2 = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
11530
11673
  const { schemaId } = this.opts;
@@ -11551,7 +11694,7 @@ var require_compile = __commonJS(function(exports) {
11551
11694
  function sameSchemaEnv(s1, s2) {
11552
11695
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
11553
11696
  }
11554
- function resolve2(root, ref) {
11697
+ function resolve3(root, ref) {
11555
11698
  let sch;
11556
11699
  while (typeof (sch = this.refs[ref]) == "string")
11557
11700
  ref = sch;
@@ -12137,7 +12280,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
12137
12280
  }
12138
12281
  return uri;
12139
12282
  }
12140
- function resolve2(baseURI, relativeURI, options) {
12283
+ function resolve3(baseURI, relativeURI, options) {
12141
12284
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
12142
12285
  const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
12143
12286
  const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
@@ -12422,7 +12565,7 @@ var require_fast_uri = __commonJS(function(exports, module) {
12422
12565
  var fastUri = {
12423
12566
  SCHEMES,
12424
12567
  normalize,
12425
- resolve: resolve2,
12568
+ resolve: resolve3,
12426
12569
  resolveComponent,
12427
12570
  equal,
12428
12571
  serialize,
@@ -14939,7 +15082,7 @@ var require_ajv = __commonJS(function(exports, module) {
14939
15082
  });
14940
15083
 
14941
15084
  // src/schema.ts
14942
- import { readFileSync as readFileSync18 } from "node:fs";
15085
+ import { existsSync as existsSync22, readFileSync as readFileSync18 } from "node:fs";
14943
15086
  import { join as join19 } from "node:path";
14944
15087
  function getValidator() {
14945
15088
  if (cachedValidate)
@@ -14950,8 +15093,22 @@ function getValidator() {
14950
15093
  return false;
14951
15094
  return !Number.isNaN(Date.parse(value));
14952
15095
  });
14953
- const schemaPath = join19(import.meta.dir, "..", "schema.json");
14954
- const schema2 = JSON.parse(readFileSync18(schemaPath, "utf8"));
15096
+ const candidates = [
15097
+ join19(import.meta.dir, "..", "schema.json"),
15098
+ join19(import.meta.dir, "schema.json"),
15099
+ join19(process.cwd(), "schema.json")
15100
+ ];
15101
+ let schemaContent = null;
15102
+ for (const p of candidates) {
15103
+ if (existsSync22(p)) {
15104
+ schemaContent = readFileSync18(p, "utf8");
15105
+ break;
15106
+ }
15107
+ }
15108
+ if (!schemaContent) {
15109
+ throw new Error(`Cannot locate schema.json in ${candidates.join(", ")}`);
15110
+ }
15111
+ const schema2 = JSON.parse(schemaContent);
14955
15112
  cachedValidate = ajv.compile(schema2);
14956
15113
  return cachedValidate;
14957
15114
  }
@@ -15057,13 +15214,13 @@ __export(exports_doctor, {
15057
15214
  printDoctorReport: () => printDoctorReport,
15058
15215
  runDoctor: () => runDoctor
15059
15216
  });
15060
- import { existsSync as existsSync22, statSync as statSync8, readFileSync as readFileSync19 } from "node:fs";
15217
+ import { existsSync as existsSync23, statSync as statSync8, readFileSync as readFileSync19 } from "node:fs";
15061
15218
  import { join as join20 } from "node:path";
15062
15219
  import { homedir as homedir5 } from "node:os";
15063
15220
  async function runDoctor(targetDir, options = {}) {
15064
15221
  const home = homedir5();
15065
15222
  const storagePath = options.global ? getGlobalMemoryDir() : findOrCreateProjectRoot(targetDir || process.cwd())?.memoryDir || join20(home, ".memory");
15066
- const isInitialized = existsSync22(storagePath);
15223
+ const isInitialized = existsSync23(storagePath);
15067
15224
  let currentMdExists = false;
15068
15225
  let currentMdLines = 0;
15069
15226
  let totalEntries = 0;
@@ -15082,7 +15239,7 @@ async function runDoctor(targetDir, options = {}) {
15082
15239
  let brokenLinksCount = 0;
15083
15240
  if (isInitialized) {
15084
15241
  const currentPath = join20(storagePath, "CURRENT.md");
15085
- if (existsSync22(currentPath)) {
15242
+ if (existsSync23(currentPath)) {
15086
15243
  currentMdExists = true;
15087
15244
  const content = readFileSync19(currentPath, "utf8");
15088
15245
  currentMdLines = content.split(`
@@ -15110,7 +15267,7 @@ async function runDoctor(targetDir, options = {}) {
15110
15267
  let auditCount = 0;
15111
15268
  let auditSize = 0;
15112
15269
  let lastEvent;
15113
- if (existsSync22(auditPath)) {
15270
+ if (existsSync23(auditPath)) {
15114
15271
  auditExists = true;
15115
15272
  try {
15116
15273
  const stat = statSync8(auditPath);
@@ -15245,7 +15402,7 @@ var init_doctor = __esm(() => {
15245
15402
  });
15246
15403
 
15247
15404
  // src/retrieval/tree-index.ts
15248
- import { existsSync as existsSync23, readFileSync as readFileSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync12, rmSync } from "node:fs";
15405
+ import { existsSync as existsSync24, readFileSync as readFileSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync12, rmSync } from "node:fs";
15249
15406
  import { join as join21 } from "node:path";
15250
15407
  function tokenize2(text) {
15251
15408
  if (!text || typeof text !== "string")
@@ -15460,7 +15617,7 @@ function buildTreeIndex(store, memoryDir, config = {}) {
15460
15617
  }
15461
15618
  function loadTreeIndex(memoryDir) {
15462
15619
  const path = globalIndexFilePath(indexDir(memoryDir));
15463
- if (!existsSync23(path))
15620
+ if (!existsSync24(path))
15464
15621
  return null;
15465
15622
  try {
15466
15623
  const data = JSON.parse(readFileSync20(path, "utf8"));
@@ -15569,7 +15726,7 @@ function searchTree(index, options) {
15569
15726
  }
15570
15727
  }
15571
15728
  results.sort((a, b) => b.score - a.score);
15572
- const paginated = paginateResults(results, options.page ?? 1, options.pageSize ?? 10);
15729
+ const paginated = paginateResults(results, options.page ?? 1, options.pageSize ?? options.maxNodes ?? 10);
15573
15730
  return {
15574
15731
  nodes: paginated,
15575
15732
  memories: [],
@@ -15608,7 +15765,7 @@ __export(exports_vector, {
15608
15765
  saveIndex: () => saveIndex,
15609
15766
  termFrequencies: () => termFrequencies
15610
15767
  });
15611
- import { existsSync as existsSync24, readFileSync as readFileSync21, writeFileSync as writeFileSync11, mkdirSync as mkdirSync13 } from "node:fs";
15768
+ import { existsSync as existsSync25, readFileSync as readFileSync21, writeFileSync as writeFileSync11, mkdirSync as mkdirSync13 } from "node:fs";
15612
15769
  import { join as join22 } from "node:path";
15613
15770
  function indexFilePath(memoryDir) {
15614
15771
  return join22(memoryDir, "index.json");
@@ -15658,13 +15815,13 @@ function rebuildIndex(store) {
15658
15815
  return index;
15659
15816
  }
15660
15817
  function saveIndex(index, memoryDir) {
15661
- if (!existsSync24(memoryDir))
15818
+ if (!existsSync25(memoryDir))
15662
15819
  mkdirSync13(memoryDir, { recursive: true });
15663
15820
  writeFileSync11(indexFilePath(memoryDir), JSON.stringify(index), "utf8");
15664
15821
  }
15665
15822
  function loadIndex(memoryDir) {
15666
15823
  const p = indexFilePath(memoryDir);
15667
- if (!existsSync24(p))
15824
+ if (!existsSync25(p))
15668
15825
  return null;
15669
15826
  try {
15670
15827
  const parsed = JSON.parse(readFileSync21(p, "utf8"));
@@ -15739,7 +15896,7 @@ var init_vector = __esm(() => {
15739
15896
  });
15740
15897
 
15741
15898
  // src/pageindex/engine.ts
15742
- import { existsSync as existsSync25, mkdirSync as mkdirSync14, readFileSync as readFileSync22, writeFileSync as writeFileSync12, rmSync as rmSync2, readdirSync as readdirSync9 } from "node:fs";
15899
+ import { existsSync as existsSync26, mkdirSync as mkdirSync14, readFileSync as readFileSync22, writeFileSync as writeFileSync12, rmSync as rmSync2, readdirSync as readdirSync9 } from "node:fs";
15743
15900
  import { join as join23 } from "node:path";
15744
15901
  function slugify2(text) {
15745
15902
  return text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 50);
@@ -15884,7 +16041,7 @@ function searchPageIndex(doc, options) {
15884
16041
  }
15885
16042
  function loadPageIndex(memoryDir, project, indexId) {
15886
16043
  const filePath = join23(memoryDir, "pageindex", project, `${indexId}.json`);
15887
- if (!existsSync25(filePath))
16044
+ if (!existsSync26(filePath))
15888
16045
  return null;
15889
16046
  try {
15890
16047
  return JSON.parse(readFileSync22(filePath, "utf8"));
@@ -15894,13 +16051,13 @@ function loadPageIndex(memoryDir, project, indexId) {
15894
16051
  }
15895
16052
  function listPageIndexes(memoryDir, project) {
15896
16053
  const base = join23(memoryDir, "pageindex");
15897
- if (!existsSync25(base))
16054
+ if (!existsSync26(base))
15898
16055
  return [];
15899
16056
  const results = [];
15900
16057
  const projects = project ? [project] : readdirSync9(base);
15901
16058
  for (const p of projects) {
15902
16059
  const pDir = join23(base, p);
15903
- if (!existsSync25(pDir))
16060
+ if (!existsSync26(pDir))
15904
16061
  continue;
15905
16062
  for (const f of readdirSync9(pDir)) {
15906
16063
  if (f.endsWith(".json")) {
@@ -15914,7 +16071,7 @@ function listPageIndexes(memoryDir, project) {
15914
16071
  }
15915
16072
  function deletePageIndex(memoryDir, project, indexId) {
15916
16073
  const base = join23(memoryDir, "pageindex");
15917
- if (!existsSync25(base))
16074
+ if (!existsSync26(base))
15918
16075
  return { deletedCount: 0 };
15919
16076
  let count = 0;
15920
16077
  if (!project && !indexId) {
@@ -15923,13 +16080,13 @@ function deletePageIndex(memoryDir, project, indexId) {
15923
16080
  }
15924
16081
  if (project && !indexId) {
15925
16082
  const pDir = join23(base, project);
15926
- if (existsSync25(pDir)) {
16083
+ if (existsSync26(pDir)) {
15927
16084
  rmSync2(pDir, { recursive: true, force: true });
15928
16085
  count++;
15929
16086
  }
15930
16087
  } else if (project && indexId) {
15931
16088
  const file = join23(base, project, `${indexId}.json`);
15932
- if (existsSync25(file)) {
16089
+ if (existsSync26(file)) {
15933
16090
  rmSync2(file, { force: true });
15934
16091
  count++;
15935
16092
  }
@@ -15942,13 +16099,13 @@ var init_engine2 = __esm(() => {
15942
16099
  });
15943
16100
 
15944
16101
  // src/retrieval/engine.ts
15945
- import { existsSync as existsSync26 } from "node:fs";
16102
+ import { existsSync as existsSync27 } from "node:fs";
15946
16103
  import { join as join24 } from "node:path";
15947
16104
 
15948
16105
  class RetrievalEngine {
15949
16106
  static search(store, memoryDir, query, options = {}) {
15950
16107
  const mode = options.mode ?? "auto";
15951
- if (mode === "pageindex" || options.docPath && existsSync26(options.docPath)) {
16108
+ if (mode === "pageindex" || options.docPath && existsSync27(options.docPath)) {
15952
16109
  try {
15953
16110
  const docs = listPageIndexes(memoryDir, options.project);
15954
16111
  if (docs.length > 0) {
@@ -15976,7 +16133,7 @@ class RetrievalEngine {
15976
16133
  } catch {}
15977
16134
  }
15978
16135
  const treeDir = join24(memoryDir, "tree");
15979
- const hasTree = existsSync26(treeDir);
16136
+ const hasTree = existsSync27(treeDir);
15980
16137
  const allEntries = list(store);
15981
16138
  if (mode === "tree" || mode === "auto" && hasTree && allEntries.length >= 500) {
15982
16139
  try {
@@ -16014,7 +16171,7 @@ class RetrievalEngine {
16014
16171
  } catch {}
16015
16172
  }
16016
16173
  const vecPath = indexFilePath(memoryDir);
16017
- const hasVec = existsSync26(vecPath);
16174
+ const hasVec = existsSync27(vecPath);
16018
16175
  if (mode === "hybrid" || mode === "auto" && hasVec && allEntries.length > 100) {
16019
16176
  try {
16020
16177
  const hybridResults = hybridSearch(store, memoryDir, query, {
@@ -16133,14 +16290,29 @@ __export(exports_ui, {
16133
16290
  });
16134
16291
  import { createServer } from "node:http";
16135
16292
  function startUiServer(opts) {
16136
- return new Promise((resolve2, reject2) => {
16293
+ return new Promise((resolve3, reject2) => {
16137
16294
  let currentPort = opts.port ?? 2222;
16138
16295
  const server = createServer(async (req, res) => {
16139
16296
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
16140
16297
  const pathname = url.pathname;
16141
- res.setHeader("Access-Control-Allow-Origin", "*");
16298
+ res.setHeader("X-Content-Type-Options", "nosniff");
16299
+ res.setHeader("X-Frame-Options", "DENY");
16300
+ res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
16301
+ res.setHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' data: https://fonts.googleapis.com https://fonts.gstatic.com; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com data:;");
16302
+ const origin = req.headers.origin;
16303
+ const isLocalOrigin = !origin || /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(origin) || origin === "null";
16304
+ if (origin && isLocalOrigin) {
16305
+ res.setHeader("Access-Control-Allow-Origin", origin);
16306
+ } else if (!origin) {
16307
+ res.setHeader("Access-Control-Allow-Origin", `http://localhost:${currentPort}`);
16308
+ }
16142
16309
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
16143
16310
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
16311
+ if (req.method === "POST" && !isLocalOrigin) {
16312
+ res.writeHead(403, { "Content-Type": "application/json" });
16313
+ res.end(JSON.stringify({ error: "Forbidden: Cross-Origin Request Blocked" }));
16314
+ return;
16315
+ }
16144
16316
  if (req.method === "OPTIONS") {
16145
16317
  res.writeHead(204);
16146
16318
  res.end();
@@ -16400,15 +16572,15 @@ function startUiServer(opts) {
16400
16572
  server.on("error", (err) => {
16401
16573
  if (err.code === "EADDRINUSE" && !opts.port) {
16402
16574
  currentPort++;
16403
- server.listen(currentPort);
16575
+ server.listen(currentPort, "127.0.0.1");
16404
16576
  } else {
16405
16577
  reject2(err);
16406
16578
  }
16407
16579
  });
16408
- server.listen(currentPort, () => {
16580
+ server.listen(currentPort, "127.0.0.1", () => {
16409
16581
  const addr = server.address();
16410
16582
  const actualPort = typeof addr === "object" && addr ? addr.port : currentPort;
16411
- resolve2({
16583
+ resolve3({
16412
16584
  port: actualPort,
16413
16585
  close: () => server.close()
16414
16586
  });
@@ -16416,12 +16588,21 @@ function startUiServer(opts) {
16416
16588
  });
16417
16589
  }
16418
16590
  function parseJsonBody(req) {
16419
- return new Promise((resolve2, reject2) => {
16591
+ return new Promise((resolve3, reject2) => {
16420
16592
  let data = "";
16421
- req.on("data", (chunk) => data += chunk);
16593
+ let byteLength = 0;
16594
+ req.on("data", (chunk) => {
16595
+ byteLength += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
16596
+ if (byteLength > MAX_BODY_SIZE) {
16597
+ req.destroy();
16598
+ reject2(new Error("Payload too large: request body exceeds 1MB limit"));
16599
+ return;
16600
+ }
16601
+ data += chunk;
16602
+ });
16422
16603
  req.on("end", () => {
16423
16604
  try {
16424
- resolve2(data ? JSON.parse(data) : {});
16605
+ resolve3(data ? JSON.parse(data) : {});
16425
16606
  } catch (e) {
16426
16607
  reject2(e);
16427
16608
  }
@@ -16435,7 +16616,7 @@ function exportStandaloneHtml(store) {
16435
16616
  return EMBEDDED_HTML.replace("</head>", `${script}
16436
16617
  </head>`);
16437
16618
  }
16438
- var EMBEDDED_HTML = `<!DOCTYPE html>
16619
+ var MAX_BODY_SIZE, EMBEDDED_HTML = `<!DOCTYPE html>
16439
16620
  <html lang="en">
16440
16621
  <head>
16441
16622
  <meta charset="UTF-8">
@@ -17434,6 +17615,7 @@ var init_ui = __esm(() => {
17434
17615
  init_retrieval2();
17435
17616
  init_schema();
17436
17617
  init_snapshot();
17618
+ MAX_BODY_SIZE = 1024 * 1024;
17437
17619
  });
17438
17620
 
17439
17621
  // node_modules/zod/v4/core/core.js
@@ -24287,7 +24469,7 @@ class Protocol {
24287
24469
  return;
24288
24470
  }
24289
24471
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
24290
- await new Promise((resolve2) => setTimeout(resolve2, pollInterval));
24472
+ await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
24291
24473
  options?.signal?.throwIfAborted();
24292
24474
  }
24293
24475
  } catch (error2) {
@@ -24299,7 +24481,7 @@ class Protocol {
24299
24481
  }
24300
24482
  request(request, resultSchema, options) {
24301
24483
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
24302
- return new Promise((resolve2, reject2) => {
24484
+ return new Promise((resolve3, reject2) => {
24303
24485
  const earlyReject = (error2) => {
24304
24486
  reject2(error2);
24305
24487
  };
@@ -24377,7 +24559,7 @@ class Protocol {
24377
24559
  if (!parseResult.success) {
24378
24560
  reject2(parseResult.error);
24379
24561
  } else {
24380
- resolve2(parseResult.data);
24562
+ resolve3(parseResult.data);
24381
24563
  }
24382
24564
  } catch (error2) {
24383
24565
  reject2(error2);
@@ -24568,12 +24750,12 @@ class Protocol {
24568
24750
  interval = task.pollInterval;
24569
24751
  }
24570
24752
  } catch {}
24571
- return new Promise((resolve2, reject2) => {
24753
+ return new Promise((resolve3, reject2) => {
24572
24754
  if (signal.aborted) {
24573
24755
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
24574
24756
  return;
24575
24757
  }
24576
- const timeoutId = setTimeout(resolve2, interval);
24758
+ const timeoutId = setTimeout(resolve3, interval);
24577
24759
  signal.addEventListener("abort", () => {
24578
24760
  clearTimeout(timeoutId);
24579
24761
  reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -25545,12 +25727,12 @@ class StdioServerTransport {
25545
25727
  this.onclose?.();
25546
25728
  }
25547
25729
  send(message) {
25548
- return new Promise((resolve2) => {
25730
+ return new Promise((resolve3) => {
25549
25731
  const json2 = serializeMessage(message);
25550
25732
  if (this._stdout.write(json2)) {
25551
- resolve2();
25733
+ resolve3();
25552
25734
  } else {
25553
- this._stdout.once("drain", resolve2);
25735
+ this._stdout.once("drain", resolve3);
25554
25736
  }
25555
25737
  });
25556
25738
  }
@@ -25685,7 +25867,7 @@ var init_loops = __esm(() => {
25685
25867
  });
25686
25868
 
25687
25869
  // src/distill.ts
25688
- import { existsSync as existsSync27, mkdirSync as mkdirSync15, writeFileSync as writeFileSync13 } from "node:fs";
25870
+ import { existsSync as existsSync28, mkdirSync as mkdirSync15, writeFileSync as writeFileSync13 } from "node:fs";
25689
25871
  import { join as join25 } from "node:path";
25690
25872
  function fixTokens(e) {
25691
25873
  const bag = tokenBag(e.title, 2);
@@ -25707,7 +25889,7 @@ function distillSkills(store, workspaceRoot, options = {}) {
25707
25889
  const slug = slugifyId(topic.join("-") || "skill");
25708
25890
  const dir = join25(skillsDir, slug);
25709
25891
  const memberIds = cluster.map((e) => e.id);
25710
- if (existsSync27(dir)) {
25892
+ if (existsSync28(dir)) {
25711
25893
  report.skippedExisting.push({ slug, members: memberIds });
25712
25894
  continue;
25713
25895
  }
@@ -25762,18 +25944,18 @@ var init_distill = __esm(() => {
25762
25944
  // src/verify.ts
25763
25945
  import { execFile } from "node:child_process";
25764
25946
  function runCommand(command, cwd, timeoutSec) {
25765
- return new Promise((resolve2) => {
25947
+ return new Promise((resolve3) => {
25766
25948
  execFile("/bin/sh", ["-c", command], { cwd, timeout: timeoutSec * 1000, killSignal: "SIGKILL", maxBuffer: 4 * 1024 * 1024 }, (err, stdout, stderr) => {
25767
25949
  if (!err) {
25768
- resolve2({ ok: true, ran: true, exitCode: 0, stdout: String(stdout), stderr: String(stderr), message: "command exited 0" });
25950
+ resolve3({ ok: true, ran: true, exitCode: 0, stdout: String(stdout), stderr: String(stderr), message: "command exited 0" });
25769
25951
  return;
25770
25952
  }
25771
25953
  const e = err;
25772
25954
  if (e.killed) {
25773
- resolve2({ ok: false, ran: true, timedOut: true, stdout: String(stdout), stderr: String(stderr), message: `timed out after ${timeoutSec}s` });
25955
+ resolve3({ ok: false, ran: true, timedOut: true, stdout: String(stdout), stderr: String(stderr), message: `timed out after ${timeoutSec}s` });
25774
25956
  return;
25775
25957
  }
25776
- resolve2({
25958
+ resolve3({
25777
25959
  ok: false,
25778
25960
  ran: true,
25779
25961
  exitCode: typeof e.code === "number" ? e.code : -1,
@@ -26058,14 +26240,14 @@ var init_schema2 = __esm(() => {
26058
26240
  });
26059
26241
 
26060
26242
  // src/settings/loader.ts
26061
- import { existsSync as existsSync28, mkdirSync as mkdirSync16, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "node:fs";
26243
+ import { existsSync as existsSync29, mkdirSync as mkdirSync16, readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "node:fs";
26062
26244
  import { join as join26 } from "node:path";
26063
26245
  function getSettingsFilePath(memoryDir) {
26064
26246
  return join26(memoryDir, "settings.json");
26065
26247
  }
26066
26248
  function loadSettings(memoryDir) {
26067
26249
  const filePath = getSettingsFilePath(memoryDir);
26068
- if (!existsSync28(filePath)) {
26250
+ if (!existsSync29(filePath)) {
26069
26251
  return {
26070
26252
  version: 1,
26071
26253
  global: JSON.parse(JSON.stringify(DEFAULT_SETTINGS)),
@@ -26220,7 +26402,7 @@ async function runMcpServer() {
26220
26402
  }
26221
26403
  return { activeStore: store, activeMemoryDir: memoryDir, activeRoot: root };
26222
26404
  }
26223
- const server = new Server({ name: "musememory", version: "1.4.0" }, {
26405
+ const server = new Server({ name: "musememory", version: "1.6.0" }, {
26224
26406
  capabilities: { tools: {}, logging: {} },
26225
26407
  instructions: `MUSE MEMORY PROTOCOL:
26226
26408
  You are equipped with Muse Memory, an autonomous persistent cognitive memory system.
@@ -26806,22 +26988,20 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26806
26988
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
26807
26989
  const { name, arguments: args } = request.params;
26808
26990
  const a = args ?? {};
26991
+ const { activeStore, activeMemoryDir, activeRoot } = resolveStoreForRequest(a);
26809
26992
  try {
26810
26993
  switch (name) {
26811
26994
  case "memory_read": {
26812
- const { activeStore } = resolveStoreForRequest(a);
26813
26995
  const entry = get2(activeStore, String(a.id));
26814
26996
  if (!entry)
26815
26997
  return toolError(`no entry with id ${a.id}`);
26816
26998
  return toolResult(entry);
26817
26999
  }
26818
27000
  case "get_context": {
26819
- const { activeStore, activeMemoryDir } = resolveStoreForRequest(a);
26820
27001
  const queryStr = String(a.query ?? "");
26821
27002
  if (queryStr && activeMemoryDir) {
26822
27003
  try {
26823
- const { updateSessionHandoff: updateSessionHandoff2 } = (init_current(), __toCommonJS(exports_current));
26824
- updateSessionHandoff2(activeMemoryDir, {
27004
+ updateSessionHandoff(activeMemoryDir, {
26825
27005
  status: "IN-PROGRESS",
26826
27006
  lastQuery: queryStr,
26827
27007
  agent: a.agent ? String(a.agent) : process.env.AGENT_NAME || "AI Assistant",
@@ -26848,10 +27028,8 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26848
27028
  });
26849
27029
  }
26850
27030
  case "memory_checkpoint": {
26851
- const { activeMemoryDir } = resolveStoreForRequest(a);
26852
27031
  try {
26853
- const { updateSessionHandoff: updateSessionHandoff2 } = (init_current(), __toCommonJS(exports_current));
26854
- const handoff = updateSessionHandoff2(activeMemoryDir, {
27032
+ const handoff = updateSessionHandoff(activeMemoryDir, {
26855
27033
  status: a.status ? String(a.status).toUpperCase() : "IN-PROGRESS",
26856
27034
  task: a.task ? String(a.task) : undefined,
26857
27035
  agent: a.agent ? String(a.agent) : process.env.AGENT_NAME || "AI Agent",
@@ -26865,7 +27043,6 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26865
27043
  case "memory_current":
26866
27044
  case "memory_get_constraints":
26867
27045
  case "memory_set_constraints": {
26868
- const { activeMemoryDir, activeRoot, activeStore } = resolveStoreForRequest(a);
26869
27046
  const action = a.action || (name === "memory_set_constraints" ? "append" : "get");
26870
27047
  if (action === "append" || a.constraint) {
26871
27048
  const text = String(a.constraint || a.text || "");
@@ -26881,7 +27058,6 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26881
27058
  }
26882
27059
  case "memory_recall":
26883
27060
  case "search": {
26884
- const { activeStore, activeMemoryDir } = resolveStoreForRequest(a);
26885
27061
  const mode = a.hybrid === true ? "hybrid" : a.tree === true ? "tree" : "auto";
26886
27062
  const res = RetrievalEngine.search(activeStore, activeMemoryDir, String(a.query), {
26887
27063
  mode,
@@ -26902,7 +27078,6 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26902
27078
  }
26903
27079
  case "propose":
26904
27080
  case "memory_capture": {
26905
- const { activeStore, activeRoot, activeMemoryDir } = resolveStoreForRequest(a);
26906
27081
  const projectName = a.project ? String(a.project) : basename(activeRoot) || "default";
26907
27082
  try {
26908
27083
  const entry = propose(activeStore, {
@@ -26920,8 +27095,7 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26920
27095
  }
26921
27096
  if (activeMemoryDir) {
26922
27097
  try {
26923
- const { updateSessionHandoff: updateSessionHandoff2 } = (init_current(), __toCommonJS(exports_current));
26924
- updateSessionHandoff2(activeMemoryDir, {
27098
+ updateSessionHandoff(activeMemoryDir, {
26925
27099
  discoveries: [String(a.title || a.content || "")]
26926
27100
  });
26927
27101
  } catch {}
@@ -26932,7 +27106,7 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26932
27106
  }
26933
27107
  }
26934
27108
  case "memory_harvest": {
26935
- const created = harvestMemories(store, {
27109
+ const created = harvestMemories(activeStore, {
26936
27110
  text: String(a.text),
26937
27111
  project: String(a.project),
26938
27112
  confirmed: a.confirmed === true
@@ -26943,11 +27117,11 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26943
27117
  const transcript = String(a.transcript);
26944
27118
  const project = a.project ? String(a.project) : undefined;
26945
27119
  const isConfirmed = a.confirmed === true;
26946
- const res = importTranscript(store, transcript, { project, confirmed: isConfirmed });
27120
+ const res = importTranscript(activeStore, transcript, { project, confirmed: isConfirmed });
26947
27121
  return toolResult(res);
26948
27122
  }
26949
27123
  case "memory_confirm": {
26950
- const entry = confirm(store, String(a.id));
27124
+ const entry = confirm(activeStore, String(a.id));
26951
27125
  if (!entry)
26952
27126
  return toolError(`could not confirm ${a.id} (not found or invalid status transition)`);
26953
27127
  return toolResult(entry);
@@ -26957,26 +27131,26 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26957
27131
  const newId = String(a.with ?? a.new_id ?? "");
26958
27132
  if (!newId)
26959
27133
  return toolError("memory_supersede requires 'with' or 'new_id' parameter");
26960
- const entry = supersede(store, oldId, newId);
27134
+ const entry = supersede(activeStore, oldId, newId);
26961
27135
  if (!entry)
26962
27136
  return toolError(`could not supersede ${oldId} with ${newId} (missing entry or target not confirmed)`);
26963
27137
  return toolResult(entry);
26964
27138
  }
26965
27139
  case "memory_link": {
26966
27140
  const related = Array.isArray(a.related) ? a.related.map(String) : [];
26967
- const entry = link2(store, String(a.id), related);
27141
+ const entry = link2(activeStore, String(a.id), related);
26968
27142
  if (!entry)
26969
27143
  return toolError(`could not link ${a.id} (missing id or related id)`);
26970
27144
  return toolResult(entry);
26971
27145
  }
26972
27146
  case "memory_mark_stale": {
26973
- const entry = markStale(store, String(a.id), a.reason ? String(a.reason) : undefined);
27147
+ const entry = markStale(activeStore, String(a.id), a.reason ? String(a.reason) : undefined);
26974
27148
  if (!entry)
26975
27149
  return toolError(`no entry with id ${a.id}`);
26976
27150
  return toolResult(entry);
26977
27151
  }
26978
27152
  case "memory_reject": {
26979
- const entry = reject(store, String(a.id));
27153
+ const entry = reject(activeStore, String(a.id));
26980
27154
  if (!entry)
26981
27155
  return toolError(`no entry with id ${a.id}`);
26982
27156
  return toolResult(entry);
@@ -26984,13 +27158,13 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26984
27158
  case "memory_delete": {
26985
27159
  const id = String(a.id);
26986
27160
  const reason = a.reason ? String(a.reason) : undefined;
26987
- const ok = deleteEntry(store, id, reason, "mcp_agent");
27161
+ const ok = deleteEntry(activeStore, id, reason, "mcp_agent");
26988
27162
  if (!ok)
26989
27163
  return toolError(`no entry found with id ${id}`);
26990
27164
  return toolResult({ success: true, deleted_id: id });
26991
27165
  }
26992
27166
  case "memory_audit": {
26993
- const trail = getAuditTrail(memoryDir, {
27167
+ const trail = getAuditTrail(activeMemoryDir, {
26994
27168
  operation: a.operation ? String(a.operation) : undefined,
26995
27169
  entryId: a.entry_id ? String(a.entry_id) : undefined,
26996
27170
  limit: typeof a.limit === "number" ? a.limit : 50
@@ -26998,37 +27172,37 @@ You are equipped with Muse Memory, an autonomous persistent cognitive memory sys
26998
27172
  return toolResult({ total: trail.length, entries: trail });
26999
27173
  }
27000
27174
  case "memory_export": {
27001
- const snapshot = exportSnapshot(store);
27175
+ const snapshot = exportSnapshot(activeStore);
27002
27176
  return toolResult(snapshot);
27003
27177
  }
27004
27178
  case "memory_import": {
27005
27179
  const entries = a.entries ?? [];
27006
- const res = importSnapshot(store, { entries }, { overwrite: a.overwrite === true });
27180
+ const res = importSnapshot(activeStore, { entries }, { overwrite: a.overwrite === true });
27007
27181
  return toolResult(res);
27008
27182
  }
27009
27183
  case "confirm_fix": {
27010
- const entry = get2(store, String(a.id));
27184
+ const entry = get2(activeStore, String(a.id));
27011
27185
  if (!entry)
27012
27186
  return toolError(`no entry with id ${a.id}`);
27013
27187
  if (entry.status !== "disputed")
27014
27188
  return toolError(`entry ${a.id} is not disputed`);
27015
- const updated = confirm(store, entry.id);
27189
+ const updated = confirm(activeStore, entry.id);
27016
27190
  if (!updated)
27017
27191
  return toolError(`no entry with id ${a.id}`);
27018
27192
  if (a.resolution) {
27019
27193
  updated.content = `${updated.content}
27020
27194
 
27021
27195
  Resolution: ${String(a.resolution)}`;
27022
- save(store, updated);
27196
+ save(activeStore, updated);
27023
27197
  }
27024
27198
  return toolResult(updated);
27025
27199
  }
27026
27200
  case "record_session": {
27027
- const { entry, sessionId } = recordSessionStart(store, String(a.project), a.note ? String(a.note) : undefined);
27201
+ const { entry, sessionId } = recordSessionStart(activeStore, String(a.project), a.note ? String(a.note) : undefined);
27028
27202
  return toolResult({ ...entry, sessionId });
27029
27203
  }
27030
27204
  case "memory_validate": {
27031
- const report = validateStore(store);
27205
+ const report = validateStore(activeStore);
27032
27206
  return toolResult(report);
27033
27207
  }
27034
27208
  case "memory_core": {
@@ -27038,41 +27212,41 @@ Resolution: ${String(a.resolution)}`;
27038
27212
  }
27039
27213
  try {
27040
27214
  if (tier && a.set !== undefined) {
27041
- const tiers = setCore(memoryDir, tier, String(a.set));
27215
+ const tiers = setCore(activeMemoryDir, tier, String(a.set));
27042
27216
  return toolResult({ tier, lines: tiers[tier] });
27043
27217
  }
27044
27218
  if (tier && a.remove === true) {
27045
- const tiers = removeCore(memoryDir, tier);
27219
+ const tiers = removeCore(activeMemoryDir, tier);
27046
27220
  return toolResult({ tier, lines: tiers[tier] });
27047
27221
  }
27048
27222
  if (tier) {
27049
- return toolResult({ tier, lines: readCore(memoryDir)[tier] });
27223
+ return toolResult({ tier, lines: readCore(activeMemoryDir)[tier] });
27050
27224
  }
27051
- return toolResult(readCore(memoryDir));
27225
+ return toolResult(readCore(activeMemoryDir));
27052
27226
  } catch (err) {
27053
27227
  return toolError(err instanceof Error ? err.message : String(err));
27054
27228
  }
27055
27229
  }
27056
27230
  case "memory_consolidate": {
27057
- const report = consolidateScenes(store, {
27231
+ const report = consolidateScenes(activeStore, {
27058
27232
  project: a.project ? String(a.project) : undefined,
27059
27233
  dryRun: a.dry_run === true
27060
27234
  });
27061
27235
  return toolResult(report);
27062
27236
  }
27063
27237
  case "memory_trace": {
27064
- const node = traceGraph(store, String(a.id), typeof a.depth === "number" ? a.depth : 5);
27238
+ const node = traceGraph(activeStore, String(a.id), typeof a.depth === "number" ? a.depth : 5);
27065
27239
  if (!node)
27066
27240
  return toolError(`no entry with id ${a.id}`);
27067
27241
  return toolResult(node);
27068
27242
  }
27069
27243
  case "memory_loops": {
27070
- const report = collectLoops(store, root, memoryDir);
27244
+ const report = collectLoops(activeStore, activeRoot, activeMemoryDir);
27071
27245
  return toolResult(report);
27072
27246
  }
27073
27247
  case "memory_distill": {
27074
27248
  try {
27075
- const report = distillSkills(store, root, {
27249
+ const report = distillSkills(activeStore, activeRoot, {
27076
27250
  minCount: typeof a.min_count === "number" ? a.min_count : undefined,
27077
27251
  dryRun: a.dry_run === true
27078
27252
  });
@@ -27082,7 +27256,7 @@ Resolution: ${String(a.resolution)}`;
27082
27256
  }
27083
27257
  }
27084
27258
  case "memory_verify": {
27085
- const result = await verifyEntry(store, root, memoryDir, String(a.id), {
27259
+ const result = await verifyEntry(activeStore, activeRoot, activeMemoryDir, String(a.id), {
27086
27260
  timeout: typeof a.timeout === "number" ? a.timeout : undefined
27087
27261
  });
27088
27262
  if (!result.ok)
@@ -27090,11 +27264,11 @@ Resolution: ${String(a.resolution)}`;
27090
27264
  return toolResult(result);
27091
27265
  }
27092
27266
  case "graph_status": {
27093
- const status = getGraphStatus(root);
27267
+ const status = getGraphStatus(activeRoot);
27094
27268
  return toolResult(status);
27095
27269
  }
27096
27270
  case "memory_detect_providers": {
27097
- const detected = detectProviders(root);
27271
+ const detected = detectProviders(activeRoot);
27098
27272
  return toolResult(detected);
27099
27273
  }
27100
27274
  case "memory_detect_agents": {
@@ -27114,7 +27288,7 @@ Resolution: ${String(a.resolution)}`;
27114
27288
  }
27115
27289
  case "memory_migrate": {
27116
27290
  try {
27117
- const report = await runMigration(store, memoryDir, {
27291
+ const report = await runMigration(activeStore, activeMemoryDir, {
27118
27292
  provider: a.provider ? String(a.provider) : undefined,
27119
27293
  all: Boolean(a.all),
27120
27294
  dryRun: Boolean(a.dry_run),
@@ -27128,7 +27302,7 @@ Resolution: ${String(a.resolution)}`;
27128
27302
  }
27129
27303
  case "memory_get_user_profile": {
27130
27304
  const isGlobal = a.global === true;
27131
- const dir = isGlobal ? getGlobalMemoryDir() : memoryDir;
27305
+ const dir = isGlobal ? getGlobalMemoryDir() : activeMemoryDir;
27132
27306
  const query = a.query ? String(a.query) : undefined;
27133
27307
  const profile = getUserProfile(dir, { query });
27134
27308
  return toolResult({ profile: profile ?? "No USER.md profile configured.", exists: Boolean(profile) });
@@ -27136,7 +27310,7 @@ Resolution: ${String(a.resolution)}`;
27136
27310
  case "memory_set_user_profile": {
27137
27311
  try {
27138
27312
  const isGlobal = a.global === true;
27139
- const dir = isGlobal ? getGlobalMemoryDir() : memoryDir;
27313
+ const dir = isGlobal ? getGlobalMemoryDir() : activeMemoryDir;
27140
27314
  setUserProfile(dir, String(a.content));
27141
27315
  return toolResult({ success: true, message: `Updated USER.md in ${dir}` });
27142
27316
  } catch (err) {
@@ -27155,9 +27329,9 @@ Resolution: ${String(a.resolution)}`;
27155
27329
  }
27156
27330
  }
27157
27331
  case "memory_tree_search": {
27158
- let index = loadTreeIndex(memoryDir);
27332
+ let index = loadTreeIndex(activeMemoryDir);
27159
27333
  if (!index) {
27160
- index = buildTreeIndex(store, memoryDir);
27334
+ index = buildTreeIndex(activeStore, activeMemoryDir);
27161
27335
  }
27162
27336
  const res = searchTree(index, {
27163
27337
  query: String(a.query),
@@ -27170,37 +27344,37 @@ Resolution: ${String(a.resolution)}`;
27170
27344
  return toolResult(res);
27171
27345
  }
27172
27346
  case "memory_wiki_get": {
27173
- const page = getWikiPage(memoryDir, String(a.slug), a.type ? String(a.type) : undefined);
27347
+ const page = getWikiPage(activeMemoryDir, String(a.slug), a.type ? String(a.type) : undefined);
27174
27348
  if (!page)
27175
27349
  return toolError(`Wiki page '${a.slug}' not found.`);
27176
27350
  return toolResult(page);
27177
27351
  }
27178
27352
  case "memory_wiki_search": {
27179
- const pages = listWikiPages(memoryDir, {
27353
+ const pages = listWikiPages(activeMemoryDir, {
27180
27354
  project: a.project ? String(a.project) : undefined,
27181
27355
  type: a.type ? String(a.type) : undefined
27182
27356
  });
27183
27357
  return toolResult({ pages, count: pages.length });
27184
27358
  }
27185
27359
  case "memory_wiki_compile": {
27186
- const res = compileWiki(store, memoryDir, {
27360
+ const res = compileWiki(activeStore, activeMemoryDir, {
27187
27361
  project: a.project ? String(a.project) : undefined,
27188
27362
  dryRun: a.dry_run === true
27189
27363
  });
27190
27364
  return toolResult(res);
27191
27365
  }
27192
27366
  case "memory_entities_get": {
27193
- const ent = findEntity(memoryDir, String(a.id));
27367
+ const ent = findEntity(activeMemoryDir, String(a.id));
27194
27368
  if (!ent)
27195
27369
  return toolError(`Entity '${a.id}' not found.`);
27196
27370
  if (a.include_related === true) {
27197
- const rel = findRelatedEntities(memoryDir, String(a.id));
27371
+ const rel = findRelatedEntities(activeMemoryDir, String(a.id));
27198
27372
  return toolResult({ entity: ent, related: rel });
27199
27373
  }
27200
27374
  return toolResult(ent);
27201
27375
  }
27202
27376
  case "memory_entities_search": {
27203
- let entities = loadEntities(memoryDir);
27377
+ let entities = loadEntities(activeMemoryDir);
27204
27378
  if (a.type)
27205
27379
  entities = entities.filter((e) => e.type === a.type);
27206
27380
  if (a.project)
@@ -27214,7 +27388,7 @@ Resolution: ${String(a.resolution)}`;
27214
27388
  title: a.title ? String(a.title) : undefined,
27215
27389
  maxDepth: typeof a.maxDepth === "number" ? a.maxDepth : undefined,
27216
27390
  dryRun: a.dryRun === true,
27217
- memoryDir
27391
+ memoryDir: activeMemoryDir
27218
27392
  });
27219
27393
  return toolResult(doc2);
27220
27394
  } catch (err) {
@@ -27223,7 +27397,7 @@ Resolution: ${String(a.resolution)}`;
27223
27397
  }
27224
27398
  case "memory_pageindex_search": {
27225
27399
  const project = a.project ? String(a.project) : "default";
27226
- const doc2 = loadPageIndex(memoryDir, project, String(a.indexId));
27400
+ const doc2 = loadPageIndex(activeMemoryDir, project, String(a.indexId));
27227
27401
  if (!doc2)
27228
27402
  return toolError(`PageIndex '${a.indexId}' not found for project '${project}'`);
27229
27403
  const res = searchPageIndex(doc2, {
@@ -27236,13 +27410,13 @@ Resolution: ${String(a.resolution)}`;
27236
27410
  }
27237
27411
  case "memory_pageindex_import": {
27238
27412
  const project = String(a.project);
27239
- const doc2 = loadPageIndex(memoryDir, project, String(a.indexId));
27413
+ const doc2 = loadPageIndex(activeMemoryDir, project, String(a.indexId));
27240
27414
  if (!doc2)
27241
27415
  return toolError(`PageIndex '${a.indexId}' not found for project '${project}'`);
27242
27416
  const search = searchPageIndex(doc2, { query: String(a.query), maxNodes: 5 });
27243
27417
  const imported = [];
27244
27418
  for (const item of search.results) {
27245
- const entry = propose(store, {
27419
+ const entry = propose(activeStore, {
27246
27420
  project,
27247
27421
  title: item.title,
27248
27422
  content: `${item.summary}
@@ -27256,20 +27430,20 @@ Path: ${item.path}`,
27256
27430
  return toolResult({ importedCount: imported.length, entries: imported });
27257
27431
  }
27258
27432
  case "memory_disconnect_pageindex": {
27259
- const res = deletePageIndex(memoryDir, a.project ? String(a.project) : undefined, a.indexId ? String(a.indexId) : undefined);
27433
+ const res = deletePageIndex(activeMemoryDir, a.project ? String(a.project) : undefined, a.indexId ? String(a.indexId) : undefined);
27260
27434
  return toolResult({ success: true, deletedIndexes: res.deletedCount });
27261
27435
  }
27262
27436
  case "memory_settings_get": {
27263
- const settings2 = a.project ? getProjectSettings(memoryDir, String(a.project)) : getSettings(memoryDir);
27437
+ const settings2 = a.project ? getProjectSettings(activeMemoryDir, String(a.project)) : getSettings(activeMemoryDir);
27264
27438
  return toolResult(settings2);
27265
27439
  }
27266
27440
  case "memory_settings_set": {
27267
27441
  try {
27268
27442
  if (a.project) {
27269
- const updated = setProjectSettings(memoryDir, String(a.project), a.settings);
27443
+ const updated = setProjectSettings(activeMemoryDir, String(a.project), a.settings);
27270
27444
  return toolResult(updated);
27271
27445
  } else {
27272
- const updated = setSettings(memoryDir, a.settings);
27446
+ const updated = setSettings(activeMemoryDir, a.settings);
27273
27447
  return toolResult(updated);
27274
27448
  }
27275
27449
  } catch (err) {
@@ -27286,9 +27460,9 @@ Path: ${item.path}`,
27286
27460
  const transport = new StdioServerTransport;
27287
27461
  await server.connect(transport);
27288
27462
  process.stdin.resume();
27289
- await new Promise((resolve2) => {
27290
- process.stdin.on("end", () => resolve2());
27291
- process.stdin.on("close", () => resolve2());
27463
+ await new Promise((resolve3) => {
27464
+ process.stdin.on("end", () => resolve3());
27465
+ process.stdin.on("close", () => resolve3());
27292
27466
  });
27293
27467
  }
27294
27468
  function toolResult(content) {
@@ -27309,7 +27483,7 @@ var init_mcp = __esm(() => {
27309
27483
  init_root();
27310
27484
  init_store();
27311
27485
  init_retrieval();
27312
- init_current();
27486
+ init_governor();
27313
27487
  init_consolidate();
27314
27488
  init_trace();
27315
27489
  init_loops();
@@ -27340,7 +27514,7 @@ __export(exports_daemon, {
27340
27514
  startHub: () => startHub
27341
27515
  });
27342
27516
  import { createServer as createServer2 } from "node:http";
27343
- import { existsSync as existsSync29 } from "node:fs";
27517
+ import { existsSync as existsSync30 } from "node:fs";
27344
27518
  import { join as join27 } from "node:path";
27345
27519
  import { watch } from "node:fs";
27346
27520
  function startHub(port, memoryDir) {
@@ -27416,20 +27590,20 @@ data: ${JSON.stringify(event)}
27416
27590
  }, DEBOUNCE_MS);
27417
27591
  };
27418
27592
  try {
27419
- if (existsSync29(memoriesDir)) {
27593
+ if (existsSync30(memoriesDir)) {
27420
27594
  watchers.push(watch(memoriesDir, () => armDebounced("memory.changed")));
27421
27595
  }
27422
27596
  const currentMd = join27(memoryDir, "CURRENT.md");
27423
- if (existsSync29(currentMd)) {
27597
+ if (existsSync30(currentMd)) {
27424
27598
  watchers.push(watch(currentMd, () => armDebounced("constraints.changed")));
27425
27599
  }
27426
27600
  } catch {}
27427
27601
  }
27428
- return new Promise((resolve2) => {
27602
+ return new Promise((resolve3) => {
27429
27603
  server.listen(port, () => {
27430
27604
  const address = server.address();
27431
27605
  const actualPort = typeof address === "object" && address ? address.port : port;
27432
- resolve2({
27606
+ resolve3({
27433
27607
  server,
27434
27608
  port: actualPort,
27435
27609
  url: `http://localhost:${actualPort}/events`,
@@ -27454,11 +27628,11 @@ var init_daemon = () => {};
27454
27628
 
27455
27629
  // src/cli/ecosystem.ts
27456
27630
  import { join as join28 } from "node:path";
27457
- import { existsSync as existsSync30, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15, readFileSync as readFileSync24 } from "node:fs";
27631
+ import { existsSync as existsSync31, mkdirSync as mkdirSync17, writeFileSync as writeFileSync15, readFileSync as readFileSync24 } from "node:fs";
27458
27632
  import { homedir as homedir6 } from "node:os";
27459
27633
  function ensureProjectAgentInstructions(targetDir) {
27460
27634
  const agentsMdPath = join28(targetDir, "AGENTS.md");
27461
- if (existsSync30(agentsMdPath)) {
27635
+ if (existsSync31(agentsMdPath)) {
27462
27636
  try {
27463
27637
  const existing = readFileSync24(agentsMdPath, "utf8");
27464
27638
  if (existing.includes("<!-- agentmemory:start -->")) {
@@ -27487,12 +27661,12 @@ async function handleInstallCommand({ positional, flags }) {
27487
27661
  mkdirSync17(join28(memoryDir, "memories"), { recursive: true });
27488
27662
  mkdirSync17(join28(globalDir, "memories"), { recursive: true });
27489
27663
  const currentPath = join28(memoryDir, "CURRENT.md");
27490
- if (!existsSync30(currentPath)) {
27664
+ if (!existsSync31(currentPath)) {
27491
27665
  writeFileSync15(currentPath, `# Active Project Constraints
27492
27666
  `, "utf8");
27493
27667
  }
27494
27668
  const globalUserPath = userFilePath(globalDir);
27495
- if (!existsSync30(globalUserPath)) {
27669
+ if (!existsSync31(globalUserPath)) {
27496
27670
  const { promptSingleSelect: promptSingleSelect2 } = await Promise.resolve().then(() => (init_prompt(), exports_prompt));
27497
27671
  const archetypeOptions = [
27498
27672
  { id: "developer", label: "Software Engineer / Developer", hint: "Code-first, direct, strict typing" },
@@ -27509,7 +27683,7 @@ async function handleInstallCommand({ positional, flags }) {
27509
27683
  ensureProjectAgentInstructions(targetDir);
27510
27684
  }
27511
27685
  const globalAgentsMd = join28(homedir6(), ".agents", "AGENTS.md");
27512
- if (existsSync30(globalAgentsMd)) {
27686
+ if (existsSync31(globalAgentsMd)) {
27513
27687
  try {
27514
27688
  const existing = readFileSync24(globalAgentsMd, "utf8");
27515
27689
  if (existing.includes("<!-- agentmemory:start -->")) {
@@ -27543,10 +27717,10 @@ async function handleInstallCommand({ positional, flags }) {
27543
27717
  }
27544
27718
  async function promptOrNotifyGitHook(targetDir, autoInstall = false) {
27545
27719
  const gitDir = join28(targetDir, ".git");
27546
- if (!existsSync30(gitDir))
27720
+ if (!existsSync31(gitDir))
27547
27721
  return false;
27548
27722
  const hookPath = join28(gitDir, "hooks", "pre-commit");
27549
- const isInstalled = existsSync30(hookPath) && readFileSync24(hookPath, "utf8").includes("memory harvest-auto");
27723
+ const isInstalled = existsSync31(hookPath) && readFileSync24(hookPath, "utf8").includes("memory harvest-auto");
27550
27724
  if (isInstalled)
27551
27725
  return true;
27552
27726
  if (autoInstall) {
@@ -27590,7 +27764,7 @@ async function handleUninstallCommand({ positional, flags }) {
27590
27764
  }
27591
27765
  if (purge) {
27592
27766
  const ctx = requireRoot(flags);
27593
- if (ctx && existsSync30(ctx.memoryDir) && !dryRun) {
27767
+ if (ctx && existsSync31(ctx.memoryDir) && !dryRun) {
27594
27768
  const { rmSync: rmSync3 } = await import("node:fs");
27595
27769
  rmSync3(ctx.memoryDir, { recursive: true, force: true });
27596
27770
  console.log(` [PURGED] Memory directory removed: ${ctx.memoryDir}`);
@@ -27608,7 +27782,7 @@ async function handleInitCommand({ positional, flags }) {
27608
27782
  const memoryDir = isGlobal ? getGlobalMemoryDir() : join28(targetDir, memoryDirName);
27609
27783
  mkdirSync17(join28(memoryDir, "memories"), { recursive: true });
27610
27784
  const currentPath = join28(memoryDir, "CURRENT.md");
27611
- if (!existsSync30(currentPath)) {
27785
+ if (!existsSync31(currentPath)) {
27612
27786
  writeFileSync15(currentPath, `# Active Project Constraints
27613
27787
  `, "utf8");
27614
27788
  }
@@ -27850,7 +28024,7 @@ var init_ecosystem = __esm(() => {
27850
28024
  });
27851
28025
 
27852
28026
  // src/agentcontract.ts
27853
- import { existsSync as existsSync31 } from "node:fs";
28027
+ import { existsSync as existsSync32 } from "node:fs";
27854
28028
  import { join as join29 } from "node:path";
27855
28029
  function parseAgentMemoryContract(markdown) {
27856
28030
  if (!markdown || !markdown.startsWith("---"))
@@ -27883,7 +28057,7 @@ function parseAgentMemoryContract(markdown) {
27883
28057
  function resolveAgentFile(nameOrPath, workspaceRoot) {
27884
28058
  if (!nameOrPath)
27885
28059
  return null;
27886
- if (existsSync31(nameOrPath))
28060
+ if (existsSync32(nameOrPath))
27887
28061
  return nameOrPath;
27888
28062
  const candidates = [
27889
28063
  join29(workspaceRoot, ".agents", `${nameOrPath}.md`),
@@ -27893,7 +28067,7 @@ function resolveAgentFile(nameOrPath, workspaceRoot) {
27893
28067
  if (home)
27894
28068
  candidates.push(join29(home, ".config", "opencode", "agents", `${nameOrPath}.md`));
27895
28069
  for (const c of candidates) {
27896
- if (existsSync31(c))
28070
+ if (existsSync32(c))
27897
28071
  return c;
27898
28072
  }
27899
28073
  return null;
@@ -27903,7 +28077,7 @@ var init_agentcontract = __esm(() => {
27903
28077
  });
27904
28078
 
27905
28079
  // src/cli/retrieval.ts
27906
- import { existsSync as existsSync32, readFileSync as readFileSync25 } from "node:fs";
28080
+ import { existsSync as existsSync33, readFileSync as readFileSync25 } from "node:fs";
27907
28081
  import { join as join30 } from "node:path";
27908
28082
  async function handleContextCommand({ positional, flags }) {
27909
28083
  let agentTypes;
@@ -28008,6 +28182,7 @@ async function handleSearchCommand({ positional, flags }) {
28008
28182
  const res = queryContext(ctx.store, positional[0], {
28009
28183
  limit,
28010
28184
  tokenBudget,
28185
+ project: flags["project"],
28011
28186
  includeSuperseded: flags["include-superseded"] === "true",
28012
28187
  type: flags["type"],
28013
28188
  status: flags["status"],
@@ -28051,7 +28226,7 @@ async function handleHarvestCommand({ positional, flags }) {
28051
28226
  const project = flags["project"];
28052
28227
  if (!project)
28053
28228
  return usageError("harvest requires --project");
28054
- const rawText = existsSync32(target) ? readFileSync25(target, "utf8") : target;
28229
+ const rawText = existsSync33(target) ? readFileSync25(target, "utf8") : target;
28055
28230
  const created = harvestMemories(ctx.store, {
28056
28231
  text: rawText,
28057
28232
  project,
@@ -28088,7 +28263,7 @@ async function handleSearchTranscriptCommand({ positional, flags }) {
28088
28263
  if (!query)
28089
28264
  return usageError("search-transcript requires <query> [file.jsonl]");
28090
28265
  const targetFile = filePath ? filePath.startsWith("/") ? filePath : join30(process.cwd(), filePath) : join30(process.cwd(), "transcript.jsonl");
28091
- if (!existsSync32(targetFile)) {
28266
+ if (!existsSync33(targetFile)) {
28092
28267
  return fail(`error: transcript file not found: ${targetFile}`);
28093
28268
  }
28094
28269
  const windowSize = flags["window"] ? parseInt(flags["window"], 10) : 2;
@@ -28434,7 +28609,7 @@ function handleEntitiesCommand(parsed) {
28434
28609
  if (!ctx)
28435
28610
  return 1;
28436
28611
  const memoryDir = ctx.memoryDir;
28437
- const sub = parsed.positional[1] ?? "list";
28612
+ const sub = parsed.positional[0] ?? "list";
28438
28613
  if (sub === "list" || sub === "ls") {
28439
28614
  const type2 = parsed.flags.type;
28440
28615
  const project = parsed.flags.project;
@@ -28455,7 +28630,7 @@ function handleEntitiesCommand(parsed) {
28455
28630
  return 0;
28456
28631
  }
28457
28632
  if (sub === "show" || sub === "get") {
28458
- const id = parsed.positional[2];
28633
+ const id = parsed.positional[1];
28459
28634
  if (!id) {
28460
28635
  console.error("Error: please specify an entity ID or name (e.g. `memory entities show nextjs`)");
28461
28636
  return 2;
@@ -28469,7 +28644,7 @@ function handleEntitiesCommand(parsed) {
28469
28644
  return 0;
28470
28645
  }
28471
28646
  if (sub === "related") {
28472
- const id = parsed.positional[2];
28647
+ const id = parsed.positional[1];
28473
28648
  if (!id) {
28474
28649
  console.error("Error: please specify an entity ID or name (e.g. `memory entities related nextjs`)");
28475
28650
  return 2;
@@ -28501,10 +28676,10 @@ function handleSettingsCommand(parsed) {
28501
28676
  if (!ctx)
28502
28677
  return 1;
28503
28678
  const memoryDir = ctx.memoryDir;
28504
- const sub = parsed.positional[1] ?? "get";
28679
+ const sub = parsed.positional[0] ?? "get";
28505
28680
  const project = parsed.flags.project;
28506
28681
  if (sub === "get") {
28507
- const key = parsed.positional[2];
28682
+ const key = parsed.positional[1];
28508
28683
  const settings2 = project ? getProjectSettings(memoryDir, project) : getSettings(memoryDir);
28509
28684
  if (key) {
28510
28685
  const parts = key.split(".");
@@ -28523,8 +28698,8 @@ function handleSettingsCommand(parsed) {
28523
28698
  return 0;
28524
28699
  }
28525
28700
  if (sub === "set") {
28526
- const key = parsed.positional[2];
28527
- const rawVal = parsed.positional[3];
28701
+ const key = parsed.positional[1];
28702
+ const rawVal = parsed.positional[2];
28528
28703
  if (!key || rawVal === undefined) {
28529
28704
  console.error("Error: please specify key and value (e.g. `memory settings set retrieval.defaultMode tree`)");
28530
28705
  return 2;
@@ -28585,7 +28760,7 @@ function handleSettingsCommand(parsed) {
28585
28760
  return 0;
28586
28761
  }
28587
28762
  if (sub === "import") {
28588
- const file = parsed.positional[2];
28763
+ const file = parsed.positional[1];
28589
28764
  if (!file) {
28590
28765
  console.error("Error: please specify a JSON file to import (e.g. `memory settings import team-settings.json`)");
28591
28766
  return 2;
@@ -28614,14 +28789,14 @@ var init_nudge = __esm(() => {
28614
28789
  });
28615
28790
 
28616
28791
  // src/routines.ts
28617
- import { readFileSync as readFileSync27, existsSync as existsSync33 } from "node:fs";
28792
+ import { readFileSync as readFileSync27, existsSync as existsSync34 } from "node:fs";
28618
28793
  import { join as join31 } from "node:path";
28619
28794
  function routinesPath(memoryDir) {
28620
28795
  return join31(memoryDir, "routines.yaml");
28621
28796
  }
28622
28797
  function loadRoutines(memoryDir) {
28623
28798
  const p = routinesPath(memoryDir);
28624
- if (!existsSync33(p))
28799
+ if (!existsSync34(p))
28625
28800
  return { routines: {} };
28626
28801
  const doc2 = yaml.load(readFileSync27(p, "utf8"), { schema: yaml.JSON_SCHEMA }) ?? {};
28627
28802
  const routines = doc2.routines ?? {};
@@ -28661,7 +28836,7 @@ var init_routines = __esm(() => {
28661
28836
  });
28662
28837
 
28663
28838
  // src/cli/lifecycle.ts
28664
- import { writeFileSync as writeFileSync17, readFileSync as readFileSync28, existsSync as existsSync34 } from "node:fs";
28839
+ import { writeFileSync as writeFileSync17, readFileSync as readFileSync28, existsSync as existsSync35 } from "node:fs";
28665
28840
  async function handleProposeCommand({ positional, flags }) {
28666
28841
  const ctx = requireRoot(flags);
28667
28842
  if (!ctx)
@@ -28824,7 +28999,7 @@ async function handleImportCommand({ positional, flags }) {
28824
28999
  const file = positional[0];
28825
29000
  if (!file)
28826
29001
  return usageError("import requires <file.json>");
28827
- if (!existsSync34(file))
29002
+ if (!existsSync35(file))
28828
29003
  return fail(`error: file ${file} does not exist`);
28829
29004
  const raw = JSON.parse(readFileSync28(file, "utf8"));
28830
29005
  const res = importSnapshot(ctx.store, raw, { overwrite: flags["overwrite"] === "true" });
@@ -28975,7 +29150,7 @@ async function handleStaleCommand({ flags }) {
28975
29150
  const daysOverride = flags["days"] ? parseInt(flags["days"], 10) : null;
28976
29151
  const now = Date.now();
28977
29152
  const stale = list(ctx.store).filter((e) => {
28978
- if (e.status !== "active")
29153
+ if (e.status !== "active" && e.status !== "confirmed")
28979
29154
  return false;
28980
29155
  const policy = stalePolicyDays(e.type);
28981
29156
  if (policy === null)