memorix 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -3212,7 +3212,7 @@ ${import_picocolors.default.gray(m3)} ${s2}
3212
3212
 
3213
3213
  // src/cli/version.ts
3214
3214
  function getCliVersion() {
3215
- return true ? "1.0.9" : pkg.version;
3215
+ return true ? "1.0.10" : pkg.version;
3216
3216
  }
3217
3217
  var init_version = __esm({
3218
3218
  "src/cli/version.ts"() {
@@ -4000,15 +4000,15 @@ function getDocumentProperties(doc, paths) {
4000
4000
  const properties = {};
4001
4001
  const pathsLength = paths.length;
4002
4002
  for (let i2 = 0; i2 < pathsLength; i2++) {
4003
- const path25 = paths[i2];
4004
- const pathTokens = path25.split(".");
4003
+ const path26 = paths[i2];
4004
+ const pathTokens = path26.split(".");
4005
4005
  let current = doc;
4006
4006
  const pathTokensLength = pathTokens.length;
4007
4007
  for (let j3 = 0; j3 < pathTokensLength; j3++) {
4008
4008
  current = current[pathTokens[j3]];
4009
4009
  if (typeof current === "object") {
4010
4010
  if (current !== null && "lat" in current && "lon" in current && typeof current.lat === "number" && typeof current.lon === "number") {
4011
- current = properties[path25] = current;
4011
+ current = properties[path26] = current;
4012
4012
  break;
4013
4013
  } else if (!Array.isArray(current) && current !== null && j3 === pathTokensLength - 1) {
4014
4014
  current = void 0;
@@ -4020,14 +4020,14 @@ function getDocumentProperties(doc, paths) {
4020
4020
  }
4021
4021
  }
4022
4022
  if (typeof current !== "undefined") {
4023
- properties[path25] = current;
4023
+ properties[path26] = current;
4024
4024
  }
4025
4025
  }
4026
4026
  return properties;
4027
4027
  }
4028
- function getNested(obj, path25) {
4029
- const props = getDocumentProperties(obj, [path25]);
4030
- return props[path25];
4028
+ function getNested(obj, path26) {
4029
+ const props = getDocumentProperties(obj, [path26]);
4030
+ return props[path26];
4031
4031
  }
4032
4032
  function convertDistanceToMeters(distance, unit) {
4033
4033
  const ratio = mapDistanceToMeters[unit];
@@ -4043,10 +4043,10 @@ function removeVectorsFromHits(searchResult, vectorProperties) {
4043
4043
  ...result.document,
4044
4044
  // Remove embeddings from the result
4045
4045
  ...vectorProperties.reduce((acc, prop) => {
4046
- const path25 = prop.split(".");
4047
- const lastKey = path25.pop();
4046
+ const path26 = prop.split(".");
4047
+ const lastKey = path26.pop();
4048
4048
  let obj = acc;
4049
- for (const key of path25) {
4049
+ for (const key of path26) {
4050
4050
  obj[key] = obj[key] ?? {};
4051
4051
  obj = obj[key];
4052
4052
  }
@@ -4778,15 +4778,15 @@ var init_avl = __esm({
4778
4778
  if (node === null) {
4779
4779
  return new AVLNode(key, [value]);
4780
4780
  }
4781
- const path25 = [];
4781
+ const path26 = [];
4782
4782
  let current = node;
4783
4783
  let parent = null;
4784
4784
  while (current !== null) {
4785
- path25.push({ parent, node: current });
4785
+ path26.push({ parent, node: current });
4786
4786
  if (key < current.k) {
4787
4787
  if (current.l === null) {
4788
4788
  current.l = new AVLNode(key, [value]);
4789
- path25.push({ parent: current, node: current.l });
4789
+ path26.push({ parent: current, node: current.l });
4790
4790
  break;
4791
4791
  } else {
4792
4792
  parent = current;
@@ -4795,7 +4795,7 @@ var init_avl = __esm({
4795
4795
  } else if (key > current.k) {
4796
4796
  if (current.r === null) {
4797
4797
  current.r = new AVLNode(key, [value]);
4798
- path25.push({ parent: current, node: current.r });
4798
+ path26.push({ parent: current, node: current.r });
4799
4799
  break;
4800
4800
  } else {
4801
4801
  parent = current;
@@ -4810,8 +4810,8 @@ var init_avl = __esm({
4810
4810
  if (this.insertCount++ % rebalanceThreshold === 0) {
4811
4811
  needRebalance = true;
4812
4812
  }
4813
- for (let i2 = path25.length - 1; i2 >= 0; i2--) {
4814
- const { parent: parent2, node: currentNode } = path25[i2];
4813
+ for (let i2 = path26.length - 1; i2 >= 0; i2--) {
4814
+ const { parent: parent2, node: currentNode } = path26[i2];
4815
4815
  currentNode.updateHeight();
4816
4816
  if (needRebalance) {
4817
4817
  const rebalancedNode = this.rebalanceNode(currentNode);
@@ -4917,10 +4917,10 @@ var init_avl = __esm({
4917
4917
  removeNode(node, key) {
4918
4918
  if (node === null)
4919
4919
  return null;
4920
- const path25 = [];
4920
+ const path26 = [];
4921
4921
  let current = node;
4922
4922
  while (current !== null && current.k !== key) {
4923
- path25.push(current);
4923
+ path26.push(current);
4924
4924
  if (key < current.k) {
4925
4925
  current = current.l;
4926
4926
  } else {
@@ -4932,10 +4932,10 @@ var init_avl = __esm({
4932
4932
  }
4933
4933
  if (current.l === null || current.r === null) {
4934
4934
  const child = current.l ? current.l : current.r;
4935
- if (path25.length === 0) {
4935
+ if (path26.length === 0) {
4936
4936
  node = child;
4937
4937
  } else {
4938
- const parent = path25[path25.length - 1];
4938
+ const parent = path26[path26.length - 1];
4939
4939
  if (parent.l === current) {
4940
4940
  parent.l = child;
4941
4941
  } else {
@@ -4958,13 +4958,13 @@ var init_avl = __esm({
4958
4958
  }
4959
4959
  current = successorParent;
4960
4960
  }
4961
- path25.push(current);
4962
- for (let i2 = path25.length - 1; i2 >= 0; i2--) {
4963
- const currentNode = path25[i2];
4961
+ path26.push(current);
4962
+ for (let i2 = path26.length - 1; i2 >= 0; i2--) {
4963
+ const currentNode = path26[i2];
4964
4964
  currentNode.updateHeight();
4965
4965
  const rebalancedNode = this.rebalanceNode(currentNode);
4966
4966
  if (i2 > 0) {
4967
- const parent = path25[i2 - 1];
4967
+ const parent = path26[i2 - 1];
4968
4968
  if (parent.l === currentNode) {
4969
4969
  parent.l = rebalancedNode;
4970
4970
  } else if (parent.r === currentNode) {
@@ -6131,15 +6131,15 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
6131
6131
  };
6132
6132
  }
6133
6133
  for (const [prop, type] of Object.entries(schema)) {
6134
- const path25 = `${prefix}${prefix ? "." : ""}${prop}`;
6134
+ const path26 = `${prefix}${prefix ? "." : ""}${prop}`;
6135
6135
  if (typeof type === "object" && !Array.isArray(type)) {
6136
- create2(orama, sharedInternalDocumentStore, type, index, path25);
6136
+ create2(orama, sharedInternalDocumentStore, type, index, path26);
6137
6137
  continue;
6138
6138
  }
6139
6139
  if (isVectorType(type)) {
6140
- index.searchableProperties.push(path25);
6141
- index.searchablePropertiesWithTypes[path25] = type;
6142
- index.vectorIndexes[path25] = {
6140
+ index.searchableProperties.push(path26);
6141
+ index.searchablePropertiesWithTypes[path26] = type;
6142
+ index.vectorIndexes[path26] = {
6143
6143
  type: "Vector",
6144
6144
  node: new VectorIndex(getVectorSize(type)),
6145
6145
  isArray: false
@@ -6149,32 +6149,32 @@ function create2(orama, sharedInternalDocumentStore, schema, index, prefix = "")
6149
6149
  switch (type) {
6150
6150
  case "boolean":
6151
6151
  case "boolean[]":
6152
- index.indexes[path25] = { type: "Bool", node: new BoolNode(), isArray };
6152
+ index.indexes[path26] = { type: "Bool", node: new BoolNode(), isArray };
6153
6153
  break;
6154
6154
  case "number":
6155
6155
  case "number[]":
6156
- index.indexes[path25] = { type: "AVL", node: new AVLTree(0, []), isArray };
6156
+ index.indexes[path26] = { type: "AVL", node: new AVLTree(0, []), isArray };
6157
6157
  break;
6158
6158
  case "string":
6159
6159
  case "string[]":
6160
- index.indexes[path25] = { type: "Radix", node: new RadixTree(), isArray };
6161
- index.avgFieldLength[path25] = 0;
6162
- index.frequencies[path25] = {};
6163
- index.tokenOccurrences[path25] = {};
6164
- index.fieldLengths[path25] = {};
6160
+ index.indexes[path26] = { type: "Radix", node: new RadixTree(), isArray };
6161
+ index.avgFieldLength[path26] = 0;
6162
+ index.frequencies[path26] = {};
6163
+ index.tokenOccurrences[path26] = {};
6164
+ index.fieldLengths[path26] = {};
6165
6165
  break;
6166
6166
  case "enum":
6167
6167
  case "enum[]":
6168
- index.indexes[path25] = { type: "Flat", node: new FlatTree(), isArray };
6168
+ index.indexes[path26] = { type: "Flat", node: new FlatTree(), isArray };
6169
6169
  break;
6170
6170
  case "geopoint":
6171
- index.indexes[path25] = { type: "BKD", node: new BKDTree(), isArray };
6171
+ index.indexes[path26] = { type: "BKD", node: new BKDTree(), isArray };
6172
6172
  break;
6173
6173
  default:
6174
- throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path25);
6174
+ throw createError("INVALID_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path26);
6175
6175
  }
6176
- index.searchableProperties.push(path25);
6177
- index.searchablePropertiesWithTypes[path25] = type;
6176
+ index.searchableProperties.push(path26);
6177
+ index.searchablePropertiesWithTypes[path26] = type;
6178
6178
  }
6179
6179
  }
6180
6180
  return index;
@@ -6745,12 +6745,12 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
6745
6745
  sorts: {}
6746
6746
  };
6747
6747
  for (const [prop, type] of Object.entries(schema)) {
6748
- const path25 = `${prefix}${prefix ? "." : ""}${prop}`;
6749
- if (sortableDeniedProperties.includes(path25)) {
6748
+ const path26 = `${prefix}${prefix ? "." : ""}${prop}`;
6749
+ if (sortableDeniedProperties.includes(path26)) {
6750
6750
  continue;
6751
6751
  }
6752
6752
  if (typeof type === "object" && !Array.isArray(type)) {
6753
- const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties, path25);
6753
+ const ret = innerCreate(orama, sharedInternalDocumentStore, type, sortableDeniedProperties, path26);
6754
6754
  safeArrayPush(sorter.sortableProperties, ret.sortableProperties);
6755
6755
  sorter.sorts = {
6756
6756
  ...sorter.sorts,
@@ -6767,9 +6767,9 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
6767
6767
  case "boolean":
6768
6768
  case "number":
6769
6769
  case "string":
6770
- sorter.sortableProperties.push(path25);
6771
- sorter.sortablePropertiesWithTypes[path25] = type;
6772
- sorter.sorts[path25] = {
6770
+ sorter.sortableProperties.push(path26);
6771
+ sorter.sortablePropertiesWithTypes[path26] = type;
6772
+ sorter.sorts[path26] = {
6773
6773
  docs: /* @__PURE__ */ new Map(),
6774
6774
  orderedDocsToRemove: /* @__PURE__ */ new Map(),
6775
6775
  orderedDocs: [],
@@ -6785,7 +6785,7 @@ function innerCreate(orama, sharedInternalDocumentStore, schema, sortableDeniedP
6785
6785
  case "string[]":
6786
6786
  continue;
6787
6787
  default:
6788
- throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path25);
6788
+ throw createError("INVALID_SORT_SCHEMA_TYPE", Array.isArray(type) ? "array" : type, path26);
6789
6789
  }
6790
6790
  }
6791
6791
  }
@@ -8630,8 +8630,8 @@ function innerFullTextSearch(orama, params, language) {
8630
8630
  function escapeRegex(str2) {
8631
8631
  return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8632
8632
  }
8633
- function getPropValue(obj, path25) {
8634
- const keys = path25.split(".");
8633
+ function getPropValue(obj, path26) {
8634
+ const keys = path26.split(".");
8635
8635
  let value = obj;
8636
8636
  for (const key of keys) {
8637
8637
  if (value && typeof value === "object" && key in value) {
@@ -15771,6 +15771,7 @@ var require_gray_matter = __commonJS({
15771
15771
  // src/config/yaml-loader.ts
15772
15772
  var yaml_loader_exports = {};
15773
15773
  __export(yaml_loader_exports, {
15774
+ clearProjectRoot: () => clearProjectRoot,
15774
15775
  initProjectRoot: () => initProjectRoot,
15775
15776
  loadYamlConfig: () => loadYamlConfig,
15776
15777
  resetYamlConfigCache: () => resetYamlConfigCache
@@ -15782,6 +15783,9 @@ function initProjectRoot(root) {
15782
15783
  globalProjectRoot = root;
15783
15784
  configCache.delete(root);
15784
15785
  }
15786
+ function clearProjectRoot() {
15787
+ globalProjectRoot = null;
15788
+ }
15785
15789
  function loadYamlConfig(projectRoot) {
15786
15790
  const resolvedRoot = projectRoot === null ? null : projectRoot ?? globalProjectRoot ?? null;
15787
15791
  const cached3 = configCache.get(resolvedRoot ?? null);
@@ -15809,6 +15813,7 @@ function loadYamlConfig(projectRoot) {
15809
15813
  ...projectConfig,
15810
15814
  // Deep merge for nested objects where both exist
15811
15815
  llm: { ...userConfig.llm, ...projectConfig.llm },
15816
+ agent: { ...userConfig.agent, ...projectConfig.agent },
15812
15817
  embedding: { ...userConfig.embedding, ...projectConfig.embedding },
15813
15818
  git: { ...userConfig.git, ...projectConfig.git },
15814
15819
  behavior: { ...userConfig.behavior, ...projectConfig.behavior },
@@ -15926,7 +15931,7 @@ var require_main = __commonJS({
15926
15931
  "use strict";
15927
15932
  init_esm_shims();
15928
15933
  var fs21 = __require("fs");
15929
- var path25 = __require("path");
15934
+ var path26 = __require("path");
15930
15935
  var os5 = __require("os");
15931
15936
  var crypto3 = __require("crypto");
15932
15937
  var packageJson = require_package();
@@ -16072,7 +16077,7 @@ var require_main = __commonJS({
16072
16077
  possibleVaultPath = options2.path.endsWith(".vault") ? options2.path : `${options2.path}.vault`;
16073
16078
  }
16074
16079
  } else {
16075
- possibleVaultPath = path25.resolve(process.cwd(), ".env.vault");
16080
+ possibleVaultPath = path26.resolve(process.cwd(), ".env.vault");
16076
16081
  }
16077
16082
  if (fs21.existsSync(possibleVaultPath)) {
16078
16083
  return possibleVaultPath;
@@ -16080,7 +16085,7 @@ var require_main = __commonJS({
16080
16085
  return null;
16081
16086
  }
16082
16087
  function _resolveHome(envPath) {
16083
- return envPath[0] === "~" ? path25.join(os5.homedir(), envPath.slice(1)) : envPath;
16088
+ return envPath[0] === "~" ? path26.join(os5.homedir(), envPath.slice(1)) : envPath;
16084
16089
  }
16085
16090
  function _configVault(options2) {
16086
16091
  const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options2 && options2.debug);
@@ -16097,7 +16102,7 @@ var require_main = __commonJS({
16097
16102
  return { parsed };
16098
16103
  }
16099
16104
  function configDotenv(options2) {
16100
- const dotenvPath = path25.resolve(process.cwd(), ".env");
16105
+ const dotenvPath = path26.resolve(process.cwd(), ".env");
16101
16106
  let encoding = "utf8";
16102
16107
  let processEnv = process.env;
16103
16108
  if (options2 && options2.processEnv != null) {
@@ -16125,13 +16130,13 @@ var require_main = __commonJS({
16125
16130
  }
16126
16131
  let lastError;
16127
16132
  const parsedAll = {};
16128
- for (const path26 of optionPaths) {
16133
+ for (const path27 of optionPaths) {
16129
16134
  try {
16130
- const parsed = DotenvModule.parse(fs21.readFileSync(path26, { encoding }));
16135
+ const parsed = DotenvModule.parse(fs21.readFileSync(path27, { encoding }));
16131
16136
  DotenvModule.populate(parsedAll, parsed, options2);
16132
16137
  } catch (e3) {
16133
16138
  if (debug) {
16134
- _debug(`Failed to load ${path26} ${e3.message}`);
16139
+ _debug(`Failed to load ${path27} ${e3.message}`);
16135
16140
  }
16136
16141
  lastError = e3;
16137
16142
  }
@@ -16144,7 +16149,7 @@ var require_main = __commonJS({
16144
16149
  const shortPaths = [];
16145
16150
  for (const filePath of optionPaths) {
16146
16151
  try {
16147
- const relative = path25.relative(process.cwd(), filePath);
16152
+ const relative = path26.relative(process.cwd(), filePath);
16148
16153
  shortPaths.push(relative);
16149
16154
  } catch (e3) {
16150
16155
  if (debug) {
@@ -16307,6 +16312,10 @@ var init_dotenv_loader = __esm({
16307
16312
  // src/config.ts
16308
16313
  var config_exports = {};
16309
16314
  __export(config_exports, {
16315
+ getAgentLLMApiKey: () => getAgentLLMApiKey,
16316
+ getAgentLLMBaseUrl: () => getAgentLLMBaseUrl,
16317
+ getAgentLLMModel: () => getAgentLLMModel,
16318
+ getAgentLLMProvider: () => getAgentLLMProvider,
16310
16319
  getEmbeddingApiKey: () => getEmbeddingApiKey,
16311
16320
  getEmbeddingBaseUrl: () => getEmbeddingBaseUrl,
16312
16321
  getEmbeddingDimensions: () => getEmbeddingDimensions,
@@ -16366,6 +16375,23 @@ function getLLMModel(providerDefault) {
16366
16375
  function getLLMBaseUrl(providerDefault) {
16367
16376
  return process.env.MEMORIX_LLM_BASE_URL || loadYamlConfig().llm?.baseUrl || loadFileConfig().llm?.baseUrl || providerDefault;
16368
16377
  }
16378
+ function getAgentLLMApiKey() {
16379
+ return process.env.MEMORIX_AGENT_LLM_API_KEY || loadYamlConfig().agent?.apiKey || loadFileConfig().agent?.apiKey || getLLMApiKey();
16380
+ }
16381
+ function getAgentLLMProvider() {
16382
+ if (process.env.MEMORIX_AGENT_LLM_PROVIDER) return process.env.MEMORIX_AGENT_LLM_PROVIDER;
16383
+ const yml = loadYamlConfig();
16384
+ if (yml.agent?.provider) return yml.agent.provider;
16385
+ const cfg = loadFileConfig();
16386
+ if (cfg.agent?.provider) return cfg.agent.provider;
16387
+ return getLLMProvider();
16388
+ }
16389
+ function getAgentLLMModel(providerDefault) {
16390
+ return process.env.MEMORIX_AGENT_LLM_MODEL || loadYamlConfig().agent?.model || loadFileConfig().agent?.model || getLLMModel(providerDefault);
16391
+ }
16392
+ function getAgentLLMBaseUrl(providerDefault) {
16393
+ return process.env.MEMORIX_AGENT_LLM_BASE_URL || loadYamlConfig().agent?.baseUrl || loadFileConfig().agent?.baseUrl || getLLMBaseUrl(providerDefault);
16394
+ }
16369
16395
  function getEmbeddingMode() {
16370
16396
  const env2 = process.env.MEMORIX_EMBEDDING?.toLowerCase()?.trim();
16371
16397
  if (env2 === "fastembed" || env2 === "transformers" || env2 === "api" || env2 === "auto") return env2;
@@ -17686,20 +17712,20 @@ async function* callLLMWithToolsStream(messages, tools) {
17686
17712
  }
17687
17713
  yield* callOpenAIWithToolsStream(messages, tools);
17688
17714
  }
17689
- function initLLM() {
17690
- const { getLLMApiKey: getLLMApiKey2, getLLMProvider: getLLMProvider2, getLLMModel: getLLMModel2, getLLMBaseUrl: getLLMBaseUrl2 } = (init_config(), __toCommonJS(config_exports));
17691
- const apiKey = getLLMApiKey2();
17715
+ function initLLM(options2 = {}) {
17716
+ const scope = options2.scope ?? "memory";
17717
+ const apiKey = scope === "agent" ? getAgentLLMApiKey() : getLLMApiKey();
17692
17718
  if (!apiKey) {
17693
17719
  currentConfig = null;
17694
17720
  return null;
17695
17721
  }
17696
- const provider2 = getLLMProvider2();
17722
+ const provider2 = scope === "agent" ? getAgentLLMProvider() : getLLMProvider();
17697
17723
  const defaults = PROVIDER_DEFAULTS[provider2] ?? PROVIDER_DEFAULTS.openai;
17698
17724
  currentConfig = {
17699
17725
  provider: provider2,
17700
17726
  apiKey,
17701
- model: getLLMModel2(defaults.model),
17702
- baseUrl: getLLMBaseUrl2(defaults.baseUrl)
17727
+ model: scope === "agent" ? getAgentLLMModel(defaults.model) : getLLMModel(defaults.model),
17728
+ baseUrl: scope === "agent" ? getAgentLLMBaseUrl(defaults.baseUrl) : getLLMBaseUrl(defaults.baseUrl)
17703
17729
  };
17704
17730
  return currentConfig;
17705
17731
  }
@@ -18206,6 +18232,7 @@ var init_provider2 = __esm({
18206
18232
  "src/llm/provider.ts"() {
18207
18233
  "use strict";
18208
18234
  init_esm_shims();
18235
+ init_config();
18209
18236
  LLM_TIMEOUT_DEFAULT_MS = 3e4;
18210
18237
  LLM_TIMEOUT_MIN_MS = 1e3;
18211
18238
  LLM_TIMEOUT_MAX_MS = 3e5;
@@ -20841,7 +20868,18 @@ __export(engine_exports, {
20841
20868
  });
20842
20869
  async function compactSearch(options2) {
20843
20870
  const entries = await searchObservations(options2);
20844
- const formatted = formatIndexTable(entries, options2.query, !options2.projectId);
20871
+ let formatted = formatIndexTable(entries, options2.query, !options2.projectId);
20872
+ if (entries.length === 0 && options2.projectId) {
20873
+ const allObservations = getAllObservations();
20874
+ const projectHasStoredMemory = allObservations.some((obs) => obs.projectId === options2.projectId);
20875
+ if (!projectHasStoredMemory) {
20876
+ formatted = `This project does not have any Memorix memories yet.
20877
+
20878
+ It looks like a fresh project: the tool call worked, but there is nothing stored to retrieve yet.
20879
+
20880
+ Memories will start appearing after observations, session summaries, hook captures, or git-memory are written.`;
20881
+ }
20882
+ }
20845
20883
  const totalTokens = countTextTokens(formatted);
20846
20884
  return { entries, formatted, totalTokens };
20847
20885
  }
@@ -21293,7 +21331,7 @@ async function askMemoryQuestion(question, history = []) {
21293
21331
  const project = detectProject(process.cwd());
21294
21332
  if (!project) {
21295
21333
  loadDotenv(process.cwd());
21296
- initLLM();
21334
+ initLLM({ scope: "agent" });
21297
21335
  if (!isLLMEnabled()) {
21298
21336
  return {
21299
21337
  question: trimmedQuestion,
@@ -21324,7 +21362,7 @@ async function askMemoryQuestion(question, history = []) {
21324
21362
  };
21325
21363
  }
21326
21364
  loadDotenv(project.rootPath);
21327
- initLLM();
21365
+ initLLM({ scope: "agent" });
21328
21366
  const dataDir = await getProjectDataDir(project.id);
21329
21367
  await prepareProjectSearch(project.id, dataDir);
21330
21368
  const searchMode = normalizeSearchMode(getLastSearchMode(project.id) || "fulltext");
@@ -21420,7 +21458,7 @@ async function askMemoryQuestionStream(question, history = [], callbacks, signal
21420
21458
  const project = detectProject(process.cwd());
21421
21459
  if (!project) {
21422
21460
  loadDotenv(process.cwd());
21423
- initLLM();
21461
+ initLLM({ scope: "agent" });
21424
21462
  if (!isLLMEnabled()) {
21425
21463
  return {
21426
21464
  question: trimmedQuestion,
@@ -21453,7 +21491,7 @@ async function askMemoryQuestionStream(question, history = [], callbacks, signal
21453
21491
  };
21454
21492
  }
21455
21493
  loadDotenv(project.rootPath);
21456
- initLLM();
21494
+ initLLM({ scope: "agent" });
21457
21495
  const dataDir = await getProjectDataDir(project.id);
21458
21496
  await prepareProjectSearch(project.id, dataDir);
21459
21497
  const searchMode = normalizeSearchMode(getLastSearchMode(project.id) || "fulltext");
@@ -22223,7 +22261,7 @@ function generateKiroHookFiles() {
22223
22261
  when: { type: "promptSubmit" },
22224
22262
  then: {
22225
22263
  type: "askAgent",
22226
- prompt: "Before responding, load context:\n1. Call memorix_session_start to get previous session summary and key memories\n2. Call memorix_search with a query related to the user's prompt for additional context\n3. If search results are found, use memorix_detail to fetch the most relevant ones\n4. Reference relevant memories naturally in your response"
22264
+ prompt: "Before responding, load useful project context:\n1. Call memorix_search with a query related to the user's prompt for relevant memories\n2. If search results are found, use memorix_detail to fetch the most relevant ones\n3. If memorix_search says this is a fresh project with no Memorix memories yet, do not repeat memorix_search again in the same turn unless the user explicitly asks for history/context or new memories were written\n4. Call memorix_session_start only when explicit session semantics are useful, such as handoff, long-running work, team coordination, or HTTP project binding\n5. Reference relevant memories naturally in your response"
22227
22265
  }
22228
22266
  }, null, 2)
22229
22267
  },
@@ -22834,20 +22872,18 @@ alwaysApply: true
22834
22872
 
22835
22873
  You have access to Memorix memory tools. Follow these rules to maintain persistent context across sessions.
22836
22874
 
22837
- ## RULE 1: Session Start \u2014 Bind Project, Then Load Context
22875
+ ## RULE 1: Use Memory When Useful
22838
22876
 
22839
- At the **beginning of every conversation**, BEFORE responding to the user:
22877
+ At the beginning of a conversation, use Memorix when prior project context would materially help the task. Do not require a session bind for every conversation.
22840
22878
 
22841
- 1. Call \`memorix_session_start\` with parameters:
22842
- - \`agent\`: your agent identifier (e.g. "windsurf", "codex", "antigravity")
22843
- - \`projectRoot\`: the **absolute path** of the current workspace or repo root
22844
- This binds the session to the correct project. Without \`projectRoot\`, memories may go to the wrong bucket.
22845
- 2. Then call \`memorix_search\` with a query related to the user's first message for additional context
22846
- 3. If search results are found, use \`memorix_detail\` to fetch the most relevant ones
22847
- 4. Reference relevant memories naturally \u2014 the user should feel you "remember" them
22879
+ 1. Call \`memorix_search\` with a query related to the user's first message or current task.
22880
+ 2. If search results are found, use \`memorix_detail\` to fetch the most relevant ones.
22881
+ 3. If \`memorix_search\` says this is a fresh project with no Memorix memories yet, treat that as a successful cold-start signal. Do not repeat \`memorix_search\` again in the same turn unless the user explicitly asks for history/context or new memories were written.
22882
+ 4. Call \`memorix_session_start\` only when explicit session semantics are useful: handoff, long-running work, team coordination, restoring prior session context, or HTTP project binding.
22883
+ 5. Reference relevant memories naturally \u2014 the user should feel you understand the project, not that you are following a ritual.
22848
22884
 
22849
22885
  **Important:** \`projectRoot\` is a detection anchor only; Git remains the source of truth for project identity.
22850
- In HTTP control-plane mode (\`memorix serve-http\` / \`memorix background start\`), explicit \`projectRoot\` binding is required for correct multi-project isolation.
22886
+ In HTTP control-plane mode (\`memorix serve-http\` / \`memorix background start\`), explicit \`projectRoot\` binding is recommended when the workspace path is available and required for correct multi-project isolation.
22851
22887
  \`memorix_session_start\` is lightweight by default: it starts memory/session context only. Do not set \`joinTeam\` unless the user explicitly needs autonomous Agent Team tasks, messages, file locks, or orchestrated CLI-agent workflows.
22852
22888
 
22853
22889
  ## RULE 2: Store Important Context
@@ -29037,8 +29073,8 @@ var init_parseUtil = __esm({
29037
29073
  init_errors2();
29038
29074
  init_en();
29039
29075
  makeIssue = (params) => {
29040
- const { data, path: path25, errorMaps, issueData } = params;
29041
- const fullPath = [...path25, ...issueData.path || []];
29076
+ const { data, path: path26, errorMaps, issueData } = params;
29077
+ const fullPath = [...path26, ...issueData.path || []];
29042
29078
  const fullIssue = {
29043
29079
  ...issueData,
29044
29080
  path: fullPath
@@ -29352,11 +29388,11 @@ var init_types3 = __esm({
29352
29388
  init_parseUtil();
29353
29389
  init_util2();
29354
29390
  ParseInputLazyPath = class {
29355
- constructor(parent, value, path25, key) {
29391
+ constructor(parent, value, path26, key) {
29356
29392
  this._cachedPath = [];
29357
29393
  this.parent = parent;
29358
29394
  this.data = value;
29359
- this._path = path25;
29395
+ this._path = path26;
29360
29396
  this._key = key;
29361
29397
  }
29362
29398
  get path() {
@@ -34032,6 +34068,189 @@ var init_poll2 = __esm({
34032
34068
  }
34033
34069
  });
34034
34070
 
34071
+ // src/cli/receipt-service.ts
34072
+ var receipt_service_exports = {};
34073
+ __export(receipt_service_exports, {
34074
+ buildHandoffReceipt: () => buildHandoffReceipt,
34075
+ formatHandoffReceipt: () => formatHandoffReceipt
34076
+ });
34077
+ import { createHash as createHash3 } from "crypto";
34078
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
34079
+ import path17 from "path";
34080
+ function sha256(value) {
34081
+ return `sha256:${createHash3("sha256").update(value).digest("hex")}`;
34082
+ }
34083
+ function hashId(projectId, id) {
34084
+ return sha256(`${projectId}:obs:${id}`);
34085
+ }
34086
+ function inferWritePolicy(observations2) {
34087
+ if (observations2.length === 0) return "not_observed";
34088
+ if (observations2.some((obs) => obs.sourceDetail === "hook")) return "hook";
34089
+ if (observations2.some((obs) => obs.sourceDetail === "explicit")) return "explicit_tool";
34090
+ if (observations2.some((obs) => obs.source === "manual")) return "cli";
34091
+ if (observations2.some((obs) => obs.source === "git" || obs.sourceDetail === "git-ingest")) return "git_ingest";
34092
+ return "agent_or_unknown";
34093
+ }
34094
+ function inferWriteTrigger(count3) {
34095
+ return count3 > 0 ? "memory_written" : "not_triggered";
34096
+ }
34097
+ function safeJsonArray(value) {
34098
+ if (Array.isArray(value)) return value;
34099
+ if (!value) return [];
34100
+ try {
34101
+ const parsed = JSON.parse(value);
34102
+ return Array.isArray(parsed) ? parsed.map(String) : [];
34103
+ } catch {
34104
+ return [];
34105
+ }
34106
+ }
34107
+ async function loadReceiptObservations(dataDir, projectId) {
34108
+ const dbPath = path17.join(dataDir, "memorix.db");
34109
+ if (existsSync8(dbPath)) {
34110
+ try {
34111
+ const DB = loadBetterSqlite3();
34112
+ const db2 = new DB(dbPath, { readonly: true, fileMustExist: true });
34113
+ try {
34114
+ return db2.prepare(`
34115
+ SELECT id, status, source, sourceDetail, title, narrative, facts
34116
+ FROM observations
34117
+ WHERE projectId = ?
34118
+ `).all(projectId);
34119
+ } finally {
34120
+ db2.close();
34121
+ }
34122
+ } catch {
34123
+ }
34124
+ }
34125
+ const jsonPath = path17.join(dataDir, "observations.json");
34126
+ if (!existsSync8(jsonPath)) return [];
34127
+ try {
34128
+ const parsed = JSON.parse(readFileSync7(jsonPath, "utf-8"));
34129
+ if (!Array.isArray(parsed)) return [];
34130
+ return parsed.filter((obs) => obs?.projectId === projectId);
34131
+ } catch {
34132
+ return [];
34133
+ }
34134
+ }
34135
+ function probeMatches(obs, probe) {
34136
+ const query = probe.toLowerCase();
34137
+ const facts = safeJsonArray(obs.facts).join(" ");
34138
+ const text = [obs.title ?? "", obs.narrative ?? "", facts].join(" ").toLowerCase();
34139
+ return query.split(/\s+/).filter(Boolean).some((term) => text.includes(term));
34140
+ }
34141
+ async function buildHandoffReceipt(options2 = {}) {
34142
+ const cwd = options2.cwd ?? process.cwd();
34143
+ const transport = options2.transport ?? "cli";
34144
+ const detection = detectProjectWithDiagnostics(cwd);
34145
+ if (!detection.project) {
34146
+ const detail = detection.failure?.detail ?? "No git repository found in the current directory.";
34147
+ throw new Error(detail);
34148
+ }
34149
+ const project = detection.project;
34150
+ const dataDir = await getProjectDataDir(project.id);
34151
+ const observations2 = (await loadReceiptObservations(dataDir, project.id)).filter((obs) => (obs.status ?? "active") === "active");
34152
+ const recent = observations2.slice(-10).reverse();
34153
+ const receipt = {
34154
+ version: 1,
34155
+ "project.has_git": true,
34156
+ "project.name_hash": sha256(project.name),
34157
+ "project.identity_hash": sha256(project.id),
34158
+ "project.root_hash": sha256(project.rootPath),
34159
+ "runtime.transport": transport,
34160
+ "runtime.cwd_hash": sha256(cwd),
34161
+ write_policy: inferWritePolicy(recent),
34162
+ "write.trigger": inferWriteTrigger(observations2.length),
34163
+ "memory.write.count": observations2.length,
34164
+ "memory.write.ids_hash": recent.map((obs) => hashId(project.id, obs.id)),
34165
+ boundary: "shared memory means stored memories are searchable across clients in the same project; chat messages are not mirrored automatically",
34166
+ privacy: {
34167
+ omitted: [
34168
+ "raw_chat_transcript",
34169
+ "raw_memory_text",
34170
+ "raw_search_query",
34171
+ "tool_arguments",
34172
+ "tool_results",
34173
+ "local_file_paths"
34174
+ ]
34175
+ }
34176
+ };
34177
+ const probe = options2.probe?.trim();
34178
+ if (probe) {
34179
+ const search3 = observations2.filter((obs) => probeMatches(obs, probe)).slice(0, 10);
34180
+ receipt["memory.search.query_hash"] = sha256(probe);
34181
+ receipt["memory.search.result_count"] = search3.length;
34182
+ receipt["memory.search.result_ids_hash"] = search3.map((entry) => hashId(project.id, entry.id));
34183
+ }
34184
+ return receipt;
34185
+ }
34186
+ function formatHandoffReceipt(receipt) {
34187
+ const lines = [
34188
+ "",
34189
+ "\u250C\u2500 Memory Handoff Receipt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
34190
+ ` Project identity: ${receipt["project.identity_hash"]}`,
34191
+ ` Git project: ${receipt["project.has_git"] ? "yes" : "no"}`,
34192
+ ` Transport: ${receipt["runtime.transport"]}`,
34193
+ ` Write policy: ${receipt.write_policy}`,
34194
+ ` Write trigger: ${receipt["write.trigger"]}`,
34195
+ ` Stored memories: ${receipt["memory.write.count"]}`
34196
+ ];
34197
+ if (typeof receipt["memory.search.result_count"] === "number") {
34198
+ lines.push(` Probe result count: ${receipt["memory.search.result_count"]}`);
34199
+ }
34200
+ lines.push("");
34201
+ lines.push(` Boundary: ${receipt.boundary}`);
34202
+ lines.push(" Privacy: raw chat, memory text, queries, tool payloads, and local paths are omitted.");
34203
+ lines.push("");
34204
+ return lines.join("\n");
34205
+ }
34206
+ var init_receipt_service = __esm({
34207
+ "src/cli/receipt-service.ts"() {
34208
+ "use strict";
34209
+ init_esm_shims();
34210
+ init_detector();
34211
+ init_persistence();
34212
+ init_sqlite_db();
34213
+ }
34214
+ });
34215
+
34216
+ // src/cli/commands/receipt.ts
34217
+ var receipt_exports = {};
34218
+ __export(receipt_exports, {
34219
+ default: () => receipt_default
34220
+ });
34221
+ var receipt_default;
34222
+ var init_receipt = __esm({
34223
+ "src/cli/commands/receipt.ts"() {
34224
+ "use strict";
34225
+ init_esm_shims();
34226
+ init_dist2();
34227
+ init_receipt_service();
34228
+ init_operator_shared();
34229
+ receipt_default = defineCommand({
34230
+ meta: {
34231
+ name: "receipt",
34232
+ description: "Generate a privacy-safe memory handoff receipt"
34233
+ },
34234
+ args: {
34235
+ json: { type: "boolean", description: "Emit machine-readable JSON output" },
34236
+ probe: { type: "string", description: "Optional search probe; only its hash is emitted" }
34237
+ },
34238
+ run: async ({ args }) => {
34239
+ const asJson = !!args.json;
34240
+ try {
34241
+ const receipt = await buildHandoffReceipt({
34242
+ probe: args.probe,
34243
+ transport: "cli"
34244
+ });
34245
+ emitResult(receipt, formatHandoffReceipt(receipt), asJson);
34246
+ } catch (error2) {
34247
+ emitError(error2 instanceof Error ? error2.message : String(error2), asJson);
34248
+ }
34249
+ }
34250
+ });
34251
+ }
34252
+ });
34253
+
34035
34254
  // src/server/tool-profile.ts
34036
34255
  function isToolInProfile(toolName, profile) {
34037
34256
  const profiles = TOOL_PROFILES[toolName];
@@ -34315,10 +34534,10 @@ function assignProp(target, prop, value) {
34315
34534
  configurable: true
34316
34535
  });
34317
34536
  }
34318
- function getElementAtPath(obj, path25) {
34319
- if (!path25)
34537
+ function getElementAtPath(obj, path26) {
34538
+ if (!path26)
34320
34539
  return obj;
34321
- return path25.reduce((acc, key) => acc?.[key], obj);
34540
+ return path26.reduce((acc, key) => acc?.[key], obj);
34322
34541
  }
34323
34542
  function promiseAllObject(promisesObj) {
34324
34543
  const keys = Object.keys(promisesObj);
@@ -34567,11 +34786,11 @@ function aborted(x3, startIndex = 0) {
34567
34786
  }
34568
34787
  return false;
34569
34788
  }
34570
- function prefixIssues(path25, issues) {
34789
+ function prefixIssues(path26, issues) {
34571
34790
  return issues.map((iss) => {
34572
34791
  var _a;
34573
34792
  (_a = iss).path ?? (_a.path = []);
34574
- iss.path.unshift(path25);
34793
+ iss.path.unshift(path26);
34575
34794
  return iss;
34576
34795
  });
34577
34796
  }
@@ -46855,8 +47074,8 @@ var require_utils2 = __commonJS({
46855
47074
  }
46856
47075
  return ind;
46857
47076
  }
46858
- function removeDotSegments(path25) {
46859
- let input = path25;
47077
+ function removeDotSegments(path26) {
47078
+ let input = path26;
46860
47079
  const output = [];
46861
47080
  let nextSlash = -1;
46862
47081
  let len = 0;
@@ -47056,8 +47275,8 @@ var require_schemes = __commonJS({
47056
47275
  wsComponent.secure = void 0;
47057
47276
  }
47058
47277
  if (wsComponent.resourceName) {
47059
- const [path25, query] = wsComponent.resourceName.split("?");
47060
- wsComponent.path = path25 && path25 !== "/" ? path25 : void 0;
47278
+ const [path26, query] = wsComponent.resourceName.split("?");
47279
+ wsComponent.path = path26 && path26 !== "/" ? path26 : void 0;
47061
47280
  wsComponent.query = query;
47062
47281
  wsComponent.resourceName = void 0;
47063
47282
  }
@@ -52041,9 +52260,9 @@ var init_auto_relations = __esm({
52041
52260
  });
52042
52261
 
52043
52262
  // src/rules/utils.ts
52044
- import { createHash as createHash3 } from "crypto";
52263
+ import { createHash as createHash4 } from "crypto";
52045
52264
  function hashContent(content) {
52046
- return createHash3("sha256").update(content.trim()).digest("hex").substring(0, 16);
52265
+ return createHash4("sha256").update(content.trim()).digest("hex").substring(0, 16);
52047
52266
  }
52048
52267
  function generateRuleId(source, filePath) {
52049
52268
  const sanitized = filePath.replace(/[\/\\]/g, "-").replace(/^\./, "");
@@ -52740,7 +52959,7 @@ __export(syncer_exports, {
52740
52959
  RulesSyncer: () => RulesSyncer
52741
52960
  });
52742
52961
  import { promises as fs13 } from "fs";
52743
- import path17 from "path";
52962
+ import path18 from "path";
52744
52963
  var RulesSyncer;
52745
52964
  var init_syncer = __esm({
52746
52965
  "src/rules/syncer.ts"() {
@@ -52786,7 +53005,7 @@ var init_syncer = __esm({
52786
53005
  for (const filePath of found) {
52787
53006
  try {
52788
53007
  const content = await fs13.readFile(filePath, "utf-8");
52789
- const relativePath = path17.relative(this.projectRoot, filePath).replace(/\\/g, "/");
53008
+ const relativePath = path18.relative(this.projectRoot, filePath).replace(/\\/g, "/");
52790
53009
  const parsed = entry.adapter.parse(relativePath, content);
52791
53010
  rules.push(...parsed);
52792
53011
  } catch {
@@ -52854,7 +53073,7 @@ var init_syncer = __esm({
52854
53073
  const entries = [];
52855
53074
  for (const adapter of this.adapters.values()) {
52856
53075
  const absolutePaths = adapter.filePatterns.map(
52857
- (p2) => path17.join(this.projectRoot, p2)
53076
+ (p2) => path18.join(this.projectRoot, p2)
52858
53077
  );
52859
53078
  entries.push({ adapter, paths: absolutePaths });
52860
53079
  }
@@ -52862,8 +53081,8 @@ var init_syncer = __esm({
52862
53081
  }
52863
53082
  /** Find files matching a glob-like path (simple implementation) */
52864
53083
  async findFiles(pattern) {
52865
- const dir = path17.dirname(pattern);
52866
- const fileGlob = path17.basename(pattern);
53084
+ const dir = path18.dirname(pattern);
53085
+ const fileGlob = path18.basename(pattern);
52867
53086
  try {
52868
53087
  const stat = await fs13.stat(dir);
52869
53088
  if (!stat.isDirectory()) {
@@ -52886,14 +53105,14 @@ var init_syncer = __esm({
52886
53105
  try {
52887
53106
  const files = await fs13.readdir(dir);
52888
53107
  const ext = fileGlob.replace("*", "");
52889
- return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) => path17.join(dir, f4));
53108
+ return files.filter((f4) => ext ? f4.endsWith(ext) : true).map((f4) => path18.join(dir, f4));
52890
53109
  } catch {
52891
53110
  return [];
52892
53111
  }
52893
53112
  }
52894
53113
  try {
52895
- await fs13.access(path17.join(dir, fileGlob));
52896
- return [path17.join(dir, fileGlob)];
53114
+ await fs13.access(path18.join(dir, fileGlob));
53115
+ return [path18.join(dir, fileGlob)];
52897
53116
  } catch {
52898
53117
  return [];
52899
53118
  }
@@ -53812,7 +54031,7 @@ var init_sanitizer = __esm({
53812
54031
  });
53813
54032
 
53814
54033
  // src/workspace/applier.ts
53815
- import { existsSync as existsSync8, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync, renameSync } from "fs";
54034
+ import { existsSync as existsSync9, mkdirSync as mkdirSync3, copyFileSync, writeFileSync as writeFileSync3, unlinkSync, renameSync } from "fs";
53816
54035
  import { dirname as dirname3 } from "path";
53817
54036
  var WorkspaceSyncApplier;
53818
54037
  var init_applier = __esm({
@@ -53843,7 +54062,7 @@ var init_applier = __esm({
53843
54062
  for (const file of files) {
53844
54063
  try {
53845
54064
  const dir = dirname3(file.filePath);
53846
- if (!existsSync8(dir)) {
54065
+ if (!existsSync9(dir)) {
53847
54066
  mkdirSync3(dir, { recursive: true });
53848
54067
  }
53849
54068
  } catch (err) {
@@ -53852,7 +54071,7 @@ var init_applier = __esm({
53852
54071
  }
53853
54072
  }
53854
54073
  for (const file of files) {
53855
- if (existsSync8(file.filePath)) {
54074
+ if (existsSync9(file.filePath)) {
53856
54075
  try {
53857
54076
  const backupPath = file.filePath + `.backup-${Date.now()}`;
53858
54077
  copyFileSync(file.filePath, backupPath);
@@ -53903,7 +54122,7 @@ var init_applier = __esm({
53903
54122
  cleanBackups(backups) {
53904
54123
  for (const backup of backups) {
53905
54124
  try {
53906
- if (existsSync8(backup.backupPath)) {
54125
+ if (existsSync9(backup.backupPath)) {
53907
54126
  unlinkSync(backup.backupPath);
53908
54127
  }
53909
54128
  } catch {
@@ -53919,7 +54138,7 @@ var engine_exports3 = {};
53919
54138
  __export(engine_exports3, {
53920
54139
  WorkspaceSyncEngine: () => WorkspaceSyncEngine
53921
54140
  });
53922
- import { readFileSync as readFileSync7, readdirSync as readdirSync3, existsSync as existsSync9, cpSync, mkdirSync as mkdirSync4 } from "fs";
54141
+ import { readFileSync as readFileSync8, readdirSync as readdirSync3, existsSync as existsSync10, cpSync, mkdirSync as mkdirSync4 } from "fs";
53923
54142
  import { join as join21 } from "path";
53924
54143
  import { homedir as homedir21 } from "os";
53925
54144
  var WorkspaceSyncEngine;
@@ -53986,10 +54205,10 @@ var init_engine3 = __esm({
53986
54205
  pathsToCheck.push(join21(homedir21(), ".gemini", "antigravity", "mcp_config.json"));
53987
54206
  }
53988
54207
  const merged = /* @__PURE__ */ new Map();
53989
- for (const path25 of pathsToCheck) {
53990
- if (existsSync9(path25)) {
54208
+ for (const path26 of pathsToCheck) {
54209
+ if (existsSync10(path26)) {
53991
54210
  try {
53992
- const content = readFileSync7(path25, "utf-8");
54211
+ const content = readFileSync8(path26, "utf-8");
53993
54212
  const servers = adapter.parse(content);
53994
54213
  for (const s2 of servers) {
53995
54214
  if (!merged.has(s2.name)) merged.set(s2.name, s2);
@@ -54041,9 +54260,9 @@ var init_engine3 = __esm({
54041
54260
  const adapter = this.adapters.get(target);
54042
54261
  const configPath = adapter.getConfigPath(this.projectRoot);
54043
54262
  let configContent;
54044
- if (target === "antigravity" && existsSync9(configPath)) {
54263
+ if (target === "antigravity" && existsSync10(configPath)) {
54045
54264
  try {
54046
- const existing = JSON.parse(readFileSync7(configPath, "utf-8"));
54265
+ const existing = JSON.parse(readFileSync8(configPath, "utf-8"));
54047
54266
  const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
54048
54267
  existing.mcpServers = { ...existing.mcpServers ?? {}, ...generated.mcpServers };
54049
54268
  configContent = JSON.stringify(existing, null, 2);
@@ -54114,16 +54333,16 @@ var init_engine3 = __esm({
54114
54333
  join21(home, dir)
54115
54334
  ];
54116
54335
  for (const skillsRoot of paths) {
54117
- if (!existsSync9(skillsRoot)) continue;
54336
+ if (!existsSync10(skillsRoot)) continue;
54118
54337
  try {
54119
54338
  const entries = readdirSync3(skillsRoot, { withFileTypes: true });
54120
54339
  for (const entry of entries) {
54121
54340
  if (!entry.isDirectory()) continue;
54122
54341
  const skillMd = join21(skillsRoot, entry.name, "SKILL.md");
54123
- if (!existsSync9(skillMd)) continue;
54342
+ if (!existsSync10(skillMd)) continue;
54124
54343
  let description = "";
54125
54344
  try {
54126
- const content = readFileSync7(skillMd, "utf-8");
54345
+ const content = readFileSync8(skillMd, "utf-8");
54127
54346
  const match = content.match(/^---[\s\S]*?description:\s*["']?(.+?)["']?\s*$/m);
54128
54347
  if (match) description = match[1];
54129
54348
  } catch {
@@ -54169,7 +54388,7 @@ var init_engine3 = __esm({
54169
54388
  for (const skill of skills) {
54170
54389
  if (skill.sourceAgent === target) continue;
54171
54390
  const dest = join21(targetDir, skill.name);
54172
- if (existsSync9(dest)) {
54391
+ if (existsSync10(dest)) {
54173
54392
  skipped.push(`${skill.name} (already exists in ${target})`);
54174
54393
  continue;
54175
54394
  }
@@ -54185,12 +54404,12 @@ var init_engine3 = __esm({
54185
54404
  scanWorkflows() {
54186
54405
  const workflows = [];
54187
54406
  const wfDir = join21(this.projectRoot, ".windsurf", "workflows");
54188
- if (!existsSync9(wfDir)) return workflows;
54407
+ if (!existsSync10(wfDir)) return workflows;
54189
54408
  try {
54190
54409
  const files = readdirSync3(wfDir).filter((f4) => f4.endsWith(".md"));
54191
54410
  for (const file of files) {
54192
54411
  try {
54193
- const content = readFileSync7(join21(wfDir, file), "utf-8");
54412
+ const content = readFileSync8(join21(wfDir, file), "utf-8");
54194
54413
  workflows.push(this.workflowSyncer.parseWindsurfWorkflow(file, content));
54195
54414
  } catch {
54196
54415
  }
@@ -54322,14 +54541,14 @@ __export(behavior_exports, {
54322
54541
  getBehaviorConfig: () => getBehaviorConfig,
54323
54542
  resetBehaviorConfigCache: () => resetBehaviorConfigCache
54324
54543
  });
54325
- import { readFileSync as readFileSync8 } from "fs";
54544
+ import { readFileSync as readFileSync9 } from "fs";
54326
54545
  import { join as join22 } from "path";
54327
54546
  import { homedir as homedir22 } from "os";
54328
54547
  function getBehaviorConfig() {
54329
54548
  if (cached2) return cached2;
54330
54549
  try {
54331
54550
  const configPath = join22(homedir22(), ".memorix", "config.json");
54332
- const raw = readFileSync8(configPath, "utf-8");
54551
+ const raw = readFileSync9(configPath, "utf-8");
54333
54552
  const config2 = JSON.parse(raw);
54334
54553
  const behavior = config2.behavior ?? {};
54335
54554
  cached2 = {
@@ -54863,11 +55082,12 @@ var init_knowledge_graph = __esm({
54863
55082
  // src/dashboard/server.ts
54864
55083
  var server_exports = {};
54865
55084
  __export(server_exports, {
55085
+ prepareDashboardConfig: () => prepareDashboardConfig,
54866
55086
  startDashboard: () => startDashboard
54867
55087
  });
54868
55088
  import { createServer } from "http";
54869
55089
  import { promises as fs14 } from "fs";
54870
- import path18 from "path";
55090
+ import path19 from "path";
54871
55091
  import { exec } from "child_process";
54872
55092
  function sendJson(res, data, status = 200) {
54873
55093
  res.writeHead(status, {
@@ -54888,6 +55108,25 @@ function isActiveStatus(status) {
54888
55108
  function filterActiveByProject(items, projectId) {
54889
55109
  return items.filter((item) => item.projectId === projectId && isActiveStatus(item.status));
54890
55110
  }
55111
+ function prepareDashboardConfig(projectRoot) {
55112
+ if (!projectRoot) {
55113
+ if (preparedDashboardProjectRoot !== null) {
55114
+ resetDotenv();
55115
+ preparedDashboardProjectRoot = null;
55116
+ }
55117
+ clearProjectRoot();
55118
+ return;
55119
+ }
55120
+ try {
55121
+ if (preparedDashboardProjectRoot !== null && preparedDashboardProjectRoot !== projectRoot) {
55122
+ resetDotenv();
55123
+ }
55124
+ initProjectRoot(projectRoot);
55125
+ loadDotenv(projectRoot);
55126
+ preparedDashboardProjectRoot = projectRoot;
55127
+ } catch {
55128
+ }
55129
+ }
54891
55130
  function computeProjectGraphCounts(allEntities, allRelations, projectObs) {
54892
55131
  const entityNames = new Set(
54893
55132
  projectObs.filter((o3) => (o3.status ?? "active") === "active" && o3.entityName).map((o3) => o3.entityName)
@@ -54913,6 +55152,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
54913
55152
  effectiveProjectResolved = true;
54914
55153
  effectiveProjectRoot = null;
54915
55154
  }
55155
+ prepareDashboardConfig(effectiveProjectRoot);
54916
55156
  try {
54917
55157
  switch (apiPath) {
54918
55158
  case "/projects": {
@@ -55161,13 +55401,13 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
55161
55401
  }
55162
55402
  case "/config": {
55163
55403
  const os5 = await import("os");
55164
- const { existsSync: existsSync18 } = await import("fs");
55404
+ const { existsSync: existsSync19 } = await import("fs");
55165
55405
  const { join: join29 } = await import("path");
55166
55406
  let yml = {};
55167
55407
  const configProjectRoot = effectiveProjectRoot;
55168
55408
  try {
55169
55409
  const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
55170
- yml = loadYamlConfig2();
55410
+ yml = configProjectRoot ? loadYamlConfig2(configProjectRoot) : loadYamlConfig2(null);
55171
55411
  } catch {
55172
55412
  }
55173
55413
  if (configProjectRoot) {
@@ -55197,7 +55437,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
55197
55437
  if (fpath === null) {
55198
55438
  files[key] = { exists: false, path: "unavailable", unavailable: true };
55199
55439
  } else {
55200
- files[key] = { exists: existsSync18(fpath), path: fpath };
55440
+ files[key] = { exists: existsSync19(fpath), path: fpath };
55201
55441
  }
55202
55442
  }
55203
55443
  } catch {
@@ -55230,6 +55470,19 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
55230
55470
  } else {
55231
55471
  values.push({ key: "llm.apiKey", value: "not set", source: "none" });
55232
55472
  }
55473
+ const agentProvider = process.env.MEMORIX_AGENT_LLM_PROVIDER || yml.agent?.provider;
55474
+ if (agentProvider) values.push({ key: "agent.llm.provider", value: agentProvider, source: await getEnvSource("MEMORIX_AGENT_LLM_PROVIDER", yml.agent?.provider ? "memorix.yml" : void 0) });
55475
+ const agentModel = process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model;
55476
+ if (agentModel) values.push({ key: "agent.llm.model", value: agentModel, source: await getEnvSource("MEMORIX_AGENT_LLM_MODEL", yml.agent?.model ? "memorix.yml" : void 0) });
55477
+ const agentKey = process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey;
55478
+ if (agentKey) {
55479
+ let src2 = "unknown";
55480
+ if (process.env.MEMORIX_AGENT_LLM_API_KEY) src2 = await getEnvSource("MEMORIX_AGENT_LLM_API_KEY");
55481
+ else if (yml.agent?.apiKey) src2 = "memorix.yml (move to .env!)";
55482
+ values.push({ key: "agent.llm.apiKey", value: "****" + agentKey.slice(-4), source: src2, sensitive: true });
55483
+ } else {
55484
+ values.push({ key: "agent.llm.apiKey", value: "fallback to llm.apiKey", source: "default" });
55485
+ }
55233
55486
  const embProvider = process.env.MEMORIX_EMBEDDING || yml.embedding?.provider || "off";
55234
55487
  values.push({ key: "embedding.provider", value: embProvider, source: await getEnvSource("MEMORIX_EMBEDDING", yml.embedding?.provider ? "memorix.yml" : void 0) });
55235
55488
  values.push({ key: "git.autoHook", value: String(yml.git?.autoHook ?? false), source: yml.git?.autoHook !== void 0 ? "memorix.yml" : "default" });
@@ -55268,7 +55521,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
55268
55521
  const aliasModule = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
55269
55522
  canonicalId = await aliasModule.getCanonicalId(effectiveProjectId);
55270
55523
  const { promises: fsP } = await import("fs");
55271
- const registryPath = path18.join(baseDir, ".project-aliases.json");
55524
+ const registryPath = path19.join(baseDir, ".project-aliases.json");
55272
55525
  const raw = await fsP.readFile(registryPath, "utf-8");
55273
55526
  const registry2 = JSON.parse(raw);
55274
55527
  aliasGroups = registry2.groups || [];
@@ -55385,14 +55638,14 @@ async function serveStatic(req, res, staticDir) {
55385
55638
  if (urlPath === "/" || !urlPath.includes(".")) {
55386
55639
  urlPath = "/index.html";
55387
55640
  }
55388
- const filePath = path18.join(staticDir, urlPath);
55641
+ const filePath = path19.join(staticDir, urlPath);
55389
55642
  if (!filePath.startsWith(staticDir)) {
55390
55643
  sendError(res, "Forbidden", 403);
55391
55644
  return;
55392
55645
  }
55393
55646
  try {
55394
55647
  const data = await fs14.readFile(filePath);
55395
- const ext = path18.extname(filePath);
55648
+ const ext = path19.extname(filePath);
55396
55649
  res.writeHead(200, {
55397
55650
  "Content-Type": MIME_TYPES[ext] || "application/octet-stream",
55398
55651
  "Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
@@ -55402,7 +55655,7 @@ async function serveStatic(req, res, staticDir) {
55402
55655
  res.end(data);
55403
55656
  } catch {
55404
55657
  try {
55405
- const indexData = await fs14.readFile(path18.join(staticDir, "index.html"));
55658
+ const indexData = await fs14.readFile(path19.join(staticDir, "index.html"));
55406
55659
  res.writeHead(200, {
55407
55660
  "Content-Type": "text/html; charset=utf-8",
55408
55661
  "Cache-Control": "no-store, no-cache, must-revalidate, max-age=0",
@@ -55665,7 +55918,7 @@ async function startDashboard(dataDir, port, staticDir, projectId, projectName,
55665
55918
  });
55666
55919
  });
55667
55920
  }
55668
- var MIME_TYPES;
55921
+ var MIME_TYPES, preparedDashboardProjectRoot;
55669
55922
  var init_server3 = __esm({
55670
55923
  "src/dashboard/server.ts"() {
55671
55924
  "use strict";
@@ -55674,6 +55927,10 @@ var init_server3 = __esm({
55674
55927
  init_obs_store();
55675
55928
  init_session_store();
55676
55929
  init_graph_store();
55930
+ init_dotenv_loader();
55931
+ init_dotenv_loader();
55932
+ init_yaml_loader();
55933
+ init_yaml_loader();
55677
55934
  MIME_TYPES = {
55678
55935
  ".html": "text/html; charset=utf-8",
55679
55936
  ".css": "text/css; charset=utf-8",
@@ -55683,6 +55940,7 @@ var init_server3 = __esm({
55683
55940
  ".png": "image/png",
55684
55941
  ".ico": "image/x-icon"
55685
55942
  };
55943
+ preparedDashboardProjectRoot = null;
55686
55944
  }
55687
55945
  });
55688
55946
 
@@ -55834,23 +56092,23 @@ __export(hooks_path_exports, {
55834
56092
  resolveGitDir: () => resolveGitDir,
55835
56093
  resolveHooksDir: () => resolveHooksDir
55836
56094
  });
55837
- import { existsSync as existsSync10, readFileSync as readFileSync9, statSync as statSync2, mkdirSync as mkdirSync5 } from "fs";
55838
- import path19 from "path";
56095
+ import { existsSync as existsSync11, readFileSync as readFileSync10, statSync as statSync2, mkdirSync as mkdirSync5 } from "fs";
56096
+ import path20 from "path";
55839
56097
  function resolveGitDir(projectRoot) {
55840
- const dotGit = path19.join(projectRoot, ".git");
55841
- if (!existsSync10(dotGit)) return null;
56098
+ const dotGit = path20.join(projectRoot, ".git");
56099
+ if (!existsSync11(dotGit)) return null;
55842
56100
  const stat = statSync2(dotGit);
55843
56101
  if (stat.isDirectory()) {
55844
56102
  return dotGit;
55845
56103
  }
55846
56104
  if (stat.isFile()) {
55847
56105
  try {
55848
- const content = readFileSync9(dotGit, "utf-8").trim();
56106
+ const content = readFileSync10(dotGit, "utf-8").trim();
55849
56107
  const match = content.match(/^gitdir:\s*(.+)$/);
55850
56108
  if (match) {
55851
56109
  const gitdir = match[1].trim();
55852
- const resolved = path19.isAbsolute(gitdir) ? gitdir : path19.resolve(projectRoot, gitdir);
55853
- if (existsSync10(resolved)) {
56110
+ const resolved = path20.isAbsolute(gitdir) ? gitdir : path20.resolve(projectRoot, gitdir);
56111
+ if (existsSync11(resolved)) {
55854
56112
  return resolved;
55855
56113
  }
55856
56114
  }
@@ -55862,10 +56120,10 @@ function resolveGitDir(projectRoot) {
55862
56120
  function resolveHooksDir(projectRoot) {
55863
56121
  const gitDir = resolveGitDir(projectRoot);
55864
56122
  if (!gitDir) return null;
55865
- const hooksDir = path19.join(gitDir, "hooks");
56123
+ const hooksDir = path20.join(gitDir, "hooks");
55866
56124
  return {
55867
56125
  hooksDir,
55868
- hookPath: path19.join(hooksDir, "post-commit")
56126
+ hookPath: path20.join(hooksDir, "post-commit")
55869
56127
  };
55870
56128
  }
55871
56129
  function ensureHooksDir(projectRoot) {
@@ -55886,7 +56144,7 @@ var server_exports2 = {};
55886
56144
  __export(server_exports2, {
55887
56145
  createMemorixServer: () => createMemorixServer
55888
56146
  });
55889
- import { createHash as createHash4 } from "crypto";
56147
+ import { createHash as createHash5 } from "crypto";
55890
56148
  import { watchFile } from "fs";
55891
56149
  function withTimeout(promise, ms, label) {
55892
56150
  let timer;
@@ -55978,7 +56236,7 @@ function coerceObjectArray(val) {
55978
56236
  return [];
55979
56237
  }
55980
56238
  function createDeterministicInstanceId(projectId, agentType, agentName) {
55981
- const digest = createHash4("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
56239
+ const digest = createHash5("sha256").update(projectId).update("\n").update(agentType).update("\n").update(agentName ?? "").digest("hex").slice(0, 24);
55982
56240
  return `auto-${digest}`;
55983
56241
  }
55984
56242
  async function createMemorixServer(cwd, existingServer, sharedTeam, options2 = {}) {
@@ -56129,7 +56387,7 @@ The path should point to a directory containing a .git folder.`
56129
56387
  };
56130
56388
  const server = existingServer ?? new McpServer({
56131
56389
  name: "memorix",
56132
- version: true ? "1.0.9" : "1.0.1"
56390
+ version: true ? "1.0.10" : "1.0.1"
56133
56391
  });
56134
56392
  const originalRegisterTool = server.registerTool.bind(server);
56135
56393
  server.registerTool = ((name, ...args) => {
@@ -57788,9 +58046,9 @@ ${skill.content}` }]
57788
58046
  lines.push(`- **Description**: ${sk.description}`);
57789
58047
  lines.push(`- **Observations**: ${sk.content.split("\n").length} lines of knowledge`);
57790
58048
  if (write && target) {
57791
- const path25 = engine.writeSkill(sk, target);
57792
- if (path25) {
57793
- lines.push(`- [OK] **Written**: \`${path25}\``);
58049
+ const path26 = engine.writeSkill(sk, target);
58050
+ if (path26) {
58051
+ lines.push(`- [OK] **Written**: \`${path26}\``);
57794
58052
  } else {
57795
58053
  lines.push(`- [ERROR] Failed to write`);
57796
58054
  }
@@ -58931,10 +59189,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
58931
59189
  const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
58932
59190
  const resolved = ensureHooksDir2(project.rootPath);
58933
59191
  if (resolved) {
58934
- const { existsSync: existsSync18, readFileSync: readFileSync17, writeFileSync: writeFileSync10, chmodSync: chmodSync2 } = await import("fs");
59192
+ const { existsSync: existsSync19, readFileSync: readFileSync18, writeFileSync: writeFileSync10, chmodSync: chmodSync2 } = await import("fs");
58935
59193
  const { hookPath } = resolved;
58936
59194
  const HOOK_MARKER3 = "# [memorix-git-hook]";
58937
- const needsInstall = !existsSync18(hookPath) || !readFileSync17(hookPath, "utf-8").includes(HOOK_MARKER3);
59195
+ const needsInstall = !existsSync19(hookPath) || !readFileSync18(hookPath, "utf-8").includes(HOOK_MARKER3);
58938
59196
  if (needsInstall) {
58939
59197
  const hookScript = `#!/bin/sh
58940
59198
  ${HOOK_MARKER3}
@@ -58943,8 +59201,8 @@ if command -v memorix >/dev/null 2>&1; then
58943
59201
  memorix ingest commit --auto >/dev/null 2>&1 &
58944
59202
  fi
58945
59203
  `;
58946
- if (existsSync18(hookPath)) {
58947
- const existing = readFileSync17(hookPath, "utf-8");
59204
+ if (existsSync19(hookPath)) {
59205
+ const existing = readFileSync18(hookPath, "utf-8");
58948
59206
  writeFileSync10(hookPath, existing.trimEnd() + `
58949
59207
 
58950
59208
  ${HOOK_MARKER3}
@@ -59393,10 +59651,12 @@ async function writeCache(cache4) {
59393
59651
  } catch {
59394
59652
  }
59395
59653
  }
59396
- function isAutoUpdateEnabled() {
59397
- const env2 = process.env.MEMORIX_AUTO_UPDATE?.toLowerCase()?.trim();
59398
- if (env2 === "off" || env2 === "false" || env2 === "0" || env2 === "notify") return false;
59399
- return true;
59654
+ function parseAutoUpdateMode(raw) {
59655
+ const env2 = raw?.toLowerCase()?.trim();
59656
+ if (!env2 || env2 === "notify") return "notify";
59657
+ if (env2 === "off" || env2 === "false" || env2 === "0") return "off";
59658
+ if (env2 === "install" || env2 === "true" || env2 === "1") return "install";
59659
+ return "notify";
59400
59660
  }
59401
59661
  function parseAutoUpdateTimeoutMs(raw) {
59402
59662
  const value = raw?.trim();
@@ -59489,7 +59749,8 @@ function installUpdateInBackground(targetVersion, currentVersion, cache4) {
59489
59749
  }
59490
59750
  async function checkForUpdates() {
59491
59751
  try {
59492
- if (!isAutoUpdateEnabled()) return;
59752
+ const mode = parseAutoUpdateMode(process.env.MEMORIX_AUTO_UPDATE);
59753
+ if (mode === "off") return;
59493
59754
  const cache4 = await readCache();
59494
59755
  const now = Date.now();
59495
59756
  if (cache4 && now - cache4.lastCheck < CHECK_INTERVAL_MS) {
@@ -59513,8 +59774,14 @@ async function checkForUpdates() {
59513
59774
  };
59514
59775
  await writeCache(updatedCache);
59515
59776
  if (isNewer(latestVersion, currentVersion)) {
59516
- console.error(`[memorix] v${latestVersion} available (current: v${currentVersion}), auto-updating...`);
59517
- installUpdateInBackground(latestVersion, currentVersion, updatedCache);
59777
+ if (mode === "install") {
59778
+ console.error(`[memorix] v${latestVersion} available (current: v${currentVersion}), auto-updating...`);
59779
+ installUpdateInBackground(latestVersion, currentVersion, updatedCache);
59780
+ } else {
59781
+ console.error(
59782
+ `[memorix] v${latestVersion} available (current: v${currentVersion}). Run "npm install -g memorix@latest" to update, or set MEMORIX_AUTO_UPDATE=install for background install.`
59783
+ );
59784
+ }
59518
59785
  }
59519
59786
  } catch {
59520
59787
  }
@@ -59537,7 +59804,7 @@ var init_update_checker = __esm({
59537
59804
  CACHE_FILE: CACHE_FILE3,
59538
59805
  CHECK_INTERVAL_MS,
59539
59806
  DEFAULT_AUTO_UPDATE_TIMEOUT_MS,
59540
- isAutoUpdateEnabled,
59807
+ parseAutoUpdateMode,
59541
59808
  parseAutoUpdateTimeoutMs,
59542
59809
  describeAutoUpdateFailure,
59543
59810
  fetchLatestVersion,
@@ -59599,14 +59866,14 @@ var init_serve = __esm({
59599
59866
  } catch {
59600
59867
  safeCwd = homedir25();
59601
59868
  }
59602
- const { existsSync: existsSync18, readFileSync: readFileSync17 } = await import("fs");
59603
- const path25 = await import("path");
59604
- const lastRootFile = path25.join(homedir25(), ".memorix", "last-project-root");
59869
+ const { existsSync: existsSync19, readFileSync: readFileSync18 } = await import("fs");
59870
+ const path26 = await import("path");
59871
+ const lastRootFile = path26.join(homedir25(), ".memorix", "last-project-root");
59605
59872
  let lastKnownProjectRoot;
59606
- if (existsSync18(lastRootFile)) {
59873
+ if (existsSync19(lastRootFile)) {
59607
59874
  try {
59608
- const lastRoot = readFileSync17(lastRootFile, "utf-8").trim();
59609
- if (lastRoot && existsSync18(lastRoot)) {
59875
+ const lastRoot = readFileSync18(lastRootFile, "utf-8").trim();
59876
+ if (lastRoot && existsSync19(lastRoot)) {
59610
59877
  lastKnownProjectRoot = lastRoot;
59611
59878
  }
59612
59879
  } catch {
@@ -59636,9 +59903,9 @@ var init_serve = __esm({
59636
59903
  if (detected) {
59637
59904
  try {
59638
59905
  const { writeFileSync: writeFileSync10, mkdirSync: mkdirSync10 } = await import("fs");
59639
- const memorixDir = path25.join(homedir25(), ".memorix");
59906
+ const memorixDir = path26.join(homedir25(), ".memorix");
59640
59907
  mkdirSync10(memorixDir, { recursive: true });
59641
- writeFileSync10(path25.join(memorixDir, "last-project-root"), detected.rootPath, "utf-8");
59908
+ writeFileSync10(path26.join(memorixDir, "last-project-root"), detected.rootPath, "utf-8");
59642
59909
  } catch {
59643
59910
  }
59644
59911
  }
@@ -61012,7 +61279,7 @@ var init_serve_http = __esm({
61012
61279
  const { isInitializeRequest: isInitializeRequest2 } = await Promise.resolve().then(() => (init_types4(), types_exports));
61013
61280
  const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
61014
61281
  const { findGitInSubdirs: findGitInSubdirs2, detectProjectWithDiagnostics: detectProjectWithDiagnostics2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
61015
- const { existsSync: existsSync18, readFileSync: readFileSync17, writeFileSync: writeFileSync10, mkdirSync: mkdirSync10 } = await import("fs");
61282
+ const { existsSync: existsSync19, readFileSync: readFileSync18, writeFileSync: writeFileSync10, mkdirSync: mkdirSync10 } = await import("fs");
61016
61283
  const { homedir: homedir25 } = await import("os");
61017
61284
  const earlyPath = await import("path");
61018
61285
  const port = parseInt(args.port || "3211", 10);
@@ -61027,10 +61294,10 @@ var init_serve_http = __esm({
61027
61294
  let projectRoot = args.cwd || process.env.MEMORIX_PROJECT_ROOT || safeCwd;
61028
61295
  const lastRootFile = earlyPath.join(homedir25(), ".memorix", "last-project-root");
61029
61296
  const initialCheck = detectProjectWithDiagnostics2(projectRoot);
61030
- if (!initialCheck.project && existsSync18(lastRootFile)) {
61297
+ if (!initialCheck.project && existsSync19(lastRootFile)) {
61031
61298
  try {
61032
- const lastRoot = readFileSync17(lastRootFile, "utf-8").trim();
61033
- if (lastRoot && existsSync18(lastRoot)) {
61299
+ const lastRoot = readFileSync18(lastRootFile, "utf-8").trim();
61300
+ if (lastRoot && existsSync19(lastRoot)) {
61034
61301
  const lastCheck = detectProjectWithDiagnostics2(lastRoot);
61035
61302
  if (lastCheck.project) {
61036
61303
  console.error(`[memorix] No git at "${projectRoot}", restored last known project: ${lastRoot}`);
@@ -61729,7 +61996,7 @@ var init_serve_http = __esm({
61729
61996
  if (apiPath === "/config") {
61730
61997
  const { projectId: configProjectId } = await resolveRequestProject(url);
61731
61998
  const os5 = await import("os");
61732
- const { existsSync: existsSync19 } = await import("fs");
61999
+ const { existsSync: existsSync20 } = await import("fs");
61733
62000
  const { join: join29 } = await import("path");
61734
62001
  const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
61735
62002
  const { loadFileConfig: loadFileConfig2, loadDotenv: loadDotenv2, getLoadedEnvFiles: getLoadedEnvFiles2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -61751,7 +62018,7 @@ var init_serve_http = __esm({
61751
62018
  "legacy config.json": join29(home, ".memorix", "config.json")
61752
62019
  };
61753
62020
  for (const [key, fpath] of Object.entries(paths)) {
61754
- files[key] = { exists: existsSync19(fpath), path: fpath };
62021
+ files[key] = { exists: existsSync20(fpath), path: fpath };
61755
62022
  }
61756
62023
  } else {
61757
62024
  files["project memorix.yml"] = { exists: false, path: "unavailable", unavailable: true };
@@ -61762,7 +62029,7 @@ var init_serve_http = __esm({
61762
62029
  "legacy config.json": join29(home, ".memorix", "config.json")
61763
62030
  };
61764
62031
  for (const [key, fpath] of Object.entries(userPaths)) {
61765
- files[key] = { exists: existsSync19(fpath), path: fpath };
62032
+ files[key] = { exists: existsSync20(fpath), path: fpath };
61766
62033
  }
61767
62034
  }
61768
62035
  const values = [];
@@ -61794,6 +62061,32 @@ var init_serve_http = __esm({
61794
62061
  } else {
61795
62062
  values.push({ key: "llm.apiKey", value: "not set", source: "none" });
61796
62063
  }
62064
+ const agentProvider = process.env.MEMORIX_AGENT_LLM_PROVIDER || yml.agent?.provider || legacy.agent?.provider;
62065
+ if (agentProvider) {
62066
+ values.push({
62067
+ key: "agent.llm.provider",
62068
+ value: agentProvider,
62069
+ source: process.env.MEMORIX_AGENT_LLM_PROVIDER ? "env:MEMORIX_AGENT_LLM_PROVIDER" : yml.agent?.provider ? "memorix.yml" : "config.json"
62070
+ });
62071
+ }
62072
+ const agentModel = process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model || legacy.agent?.model;
62073
+ if (agentModel) {
62074
+ values.push({
62075
+ key: "agent.llm.model",
62076
+ value: agentModel,
62077
+ source: process.env.MEMORIX_AGENT_LLM_MODEL ? "env:MEMORIX_AGENT_LLM_MODEL" : yml.agent?.model ? "memorix.yml" : "config.json"
62078
+ });
62079
+ }
62080
+ const agentKey = process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey || legacy.agent?.apiKey;
62081
+ if (agentKey) {
62082
+ let src2 = "unknown";
62083
+ if (process.env.MEMORIX_AGENT_LLM_API_KEY) src2 = "env:MEMORIX_AGENT_LLM_API_KEY";
62084
+ else if (yml.agent?.apiKey) src2 = "memorix.yml (move to .env!)";
62085
+ else if (legacy.agent?.apiKey) src2 = "config.json (legacy)";
62086
+ values.push({ key: "agent.llm.apiKey", value: "****" + agentKey.slice(-4), source: src2, sensitive: true });
62087
+ } else {
62088
+ values.push({ key: "agent.llm.apiKey", value: "fallback to llm.apiKey", source: "default" });
62089
+ }
61797
62090
  const embProvider = process.env.MEMORIX_EMBEDDING || yml.embedding?.provider || legacy.embedding || "off";
61798
62091
  values.push({
61799
62092
  key: "embedding.provider",
@@ -62204,7 +62497,7 @@ var init_status = __esm({
62204
62497
  const { RulesSyncer: RulesSyncer2 } = await Promise.resolve().then(() => (init_syncer(), syncer_exports));
62205
62498
  const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
62206
62499
  const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
62207
- const { existsSync: existsSync18, readFileSync: readFileSync17 } = await import("fs");
62500
+ const { existsSync: existsSync19, readFileSync: readFileSync18 } = await import("fs");
62208
62501
  const { join: join29 } = await import("path");
62209
62502
  we("memorix status");
62210
62503
  const project = detectProject2();
@@ -62279,11 +62572,11 @@ Embedding: ${embeddingStatus}${embeddingHint}`,
62279
62572
  const userEnv = join29(os5.homedir(), ".memorix", ".env");
62280
62573
  const legacyJson = join29(os5.homedir(), ".memorix", "config.json");
62281
62574
  diagLines.push("Config files:");
62282
- diagLines.push(` memorix.yml (project): ${existsSync18(projectYml) ? "[OK] " + projectYml : "[ERROR] not found"}`);
62283
- diagLines.push(` memorix.yml (user): ${existsSync18(userYml) ? "[OK] " + userYml : "\u2014 not found"}`);
62284
- diagLines.push(` .env (project): ${existsSync18(projectEnv) ? "[OK] " + projectEnv : "\u2014 not found"}`);
62285
- diagLines.push(` .env (user): ${existsSync18(userEnv) ? "[OK] " + userEnv : "\u2014 not found"}`);
62286
- diagLines.push(` config.json (legacy): ${existsSync18(legacyJson) ? "[WARN] " + legacyJson : "\u2014 not found"}`);
62575
+ diagLines.push(` memorix.yml (project): ${existsSync19(projectYml) ? "[OK] " + projectYml : "[ERROR] not found"}`);
62576
+ diagLines.push(` memorix.yml (user): ${existsSync19(userYml) ? "[OK] " + userYml : "\u2014 not found"}`);
62577
+ diagLines.push(` .env (project): ${existsSync19(projectEnv) ? "[OK] " + projectEnv : "\u2014 not found"}`);
62578
+ diagLines.push(` .env (user): ${existsSync19(userEnv) ? "[OK] " + userEnv : "\u2014 not found"}`);
62579
+ diagLines.push(` config.json (legacy): ${existsSync19(legacyJson) ? "[WARN] " + legacyJson : "\u2014 not found"}`);
62287
62580
  const loadedEnv = getLoadedEnvFiles2();
62288
62581
  if (loadedEnv.length > 0) {
62289
62582
  diagLines.push(` Loaded .env files: ${loadedEnv.join(", ")}`);
@@ -62312,6 +62605,23 @@ Embedding: ${embeddingStatus}${embeddingHint}`,
62312
62605
  } else {
62313
62606
  diagLines.push(` LLM API key: not set`);
62314
62607
  }
62608
+ const agentProvider = process.env.MEMORIX_AGENT_LLM_PROVIDER || yml.agent?.provider || legacy.agent?.provider;
62609
+ if (agentProvider) {
62610
+ const src2 = process.env.MEMORIX_AGENT_LLM_PROVIDER ? "env:MEMORIX_AGENT_LLM_PROVIDER" : yml.agent?.provider ? "memorix.yml" : "config.json";
62611
+ diagLines.push(` Agent LLM provider: ${agentProvider} (\u2190 ${src2})`);
62612
+ }
62613
+ const agentModel = process.env.MEMORIX_AGENT_LLM_MODEL || yml.agent?.model || legacy.agent?.model;
62614
+ if (agentModel) {
62615
+ const src2 = process.env.MEMORIX_AGENT_LLM_MODEL ? "env:MEMORIX_AGENT_LLM_MODEL" : yml.agent?.model ? "memorix.yml" : "config.json";
62616
+ diagLines.push(` Agent LLM model: ${agentModel} (\u2190 ${src2})`);
62617
+ }
62618
+ const agentKey = process.env.MEMORIX_AGENT_LLM_API_KEY || yml.agent?.apiKey || legacy.agent?.apiKey;
62619
+ if (agentKey) {
62620
+ const src2 = process.env.MEMORIX_AGENT_LLM_API_KEY ? "env:MEMORIX_AGENT_LLM_API_KEY" : yml.agent?.apiKey ? "memorix.yml (consider moving to .env)" : "config.json (legacy)";
62621
+ diagLines.push(` Agent LLM API key: ${"*".repeat(8)}...${agentKey.slice(-4)} (\u2190 ${src2})`);
62622
+ } else {
62623
+ diagLines.push(` Agent LLM: falls back to LLM config`);
62624
+ }
62315
62625
  const embMode = process.env.MEMORIX_EMBEDDING || yml.embedding?.provider || legacy.embedding || "off";
62316
62626
  const embSrc = process.env.MEMORIX_EMBEDDING ? "env" : yml.embedding?.provider ? "memorix.yml" : legacy.embedding ? "config.json" : "default";
62317
62627
  diagLines.push(` Embedding: ${embMode} (\u2190 ${embSrc})`);
@@ -62326,8 +62636,8 @@ Embedding: ${embeddingStatus}${embeddingHint}`,
62326
62636
  try {
62327
62637
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
62328
62638
  const resolved = resolveHooksDir2(project.rootPath);
62329
- if (resolved && existsSync18(resolved.hookPath)) {
62330
- const hookContent = readFileSync17(resolved.hookPath, "utf-8");
62639
+ if (resolved && existsSync19(resolved.hookPath)) {
62640
+ const hookContent = readFileSync18(resolved.hookPath, "utf-8");
62331
62641
  if (hookContent.includes("# [memorix-git-hook]")) {
62332
62642
  diagLines.push(` Git hook: installed [OK]`);
62333
62643
  } else {
@@ -62338,7 +62648,7 @@ Embedding: ${embeddingStatus}${embeddingHint}`,
62338
62648
  }
62339
62649
  } catch {
62340
62650
  }
62341
- if (!existsSync18(projectYml)) {
62651
+ if (!existsSync19(projectYml)) {
62342
62652
  diagLines.push("");
62343
62653
  diagLines.push('[TIP] Run "memorix init" to create memorix.yml + .env');
62344
62654
  }
@@ -62529,7 +62839,7 @@ var init_sync = __esm({
62529
62839
  const { detectProject: detectProject2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
62530
62840
  const { RulesSyncer: RulesSyncer2 } = await Promise.resolve().then(() => (init_syncer(), syncer_exports));
62531
62841
  const { promises: fs21 } = await import("fs");
62532
- const path25 = await import("path");
62842
+ const path26 = await import("path");
62533
62843
  we("memorix sync");
62534
62844
  const project = detectProject2();
62535
62845
  if (!project) {
@@ -62601,8 +62911,8 @@ var init_sync = __esm({
62601
62911
  process.exit(0);
62602
62912
  }
62603
62913
  for (const file of files) {
62604
- const fullPath = path25.join(project.rootPath, file.filePath);
62605
- await fs21.mkdir(path25.dirname(fullPath), { recursive: true });
62914
+ const fullPath = path26.join(project.rootPath, file.filePath);
62915
+ await fs21.mkdir(path26.dirname(fullPath), { recursive: true });
62606
62916
  await fs21.writeFile(fullPath, file.content, "utf-8");
62607
62917
  v3.success(`Written: ${file.filePath}`);
62608
62918
  }
@@ -63583,9 +63893,9 @@ ${lines.join("\n")}`;
63583
63893
  }
63584
63894
  let systemMessage;
63585
63895
  if (injectMode === "full" && contextSummary) {
63586
- systemMessage = `Previous session context available. Use memorix_search if needed.${contextSummary}`;
63896
+ systemMessage = `Previous session context may be available. Use memorix_search when prior project context would materially help. If search reports a fresh project with no Memorix memories yet, treat that as a cold-start signal and do not repeat the search in the same turn.${contextSummary}`;
63587
63897
  } else {
63588
- systemMessage = "Previous session context available. Use memorix_search if needed.";
63898
+ systemMessage = "Previous session context may be available. Use memorix_search when prior project context would materially help. If search reports a fresh project with no Memorix memories yet, do not repeat the search in the same turn.";
63589
63899
  }
63590
63900
  return {
63591
63901
  observation: null,
@@ -64038,7 +64348,7 @@ __export(hooks_preview_exports, {
64038
64348
  default: () => hooks_preview_default
64039
64349
  });
64040
64350
  import * as fs15 from "fs/promises";
64041
- import * as path20 from "path";
64351
+ import * as path21 from "path";
64042
64352
  function estimateFileSize(agent, configPath) {
64043
64353
  const sizes = {
64044
64354
  claude: "~2KB",
@@ -64058,30 +64368,30 @@ function getRulesPath(agent, cwd, global2) {
64058
64368
  if (global2) {
64059
64369
  switch (agent) {
64060
64370
  case "cursor":
64061
- return path20.join(home, ".cursor", "rules", "memorix.mdc");
64371
+ return path21.join(home, ".cursor", "rules", "memorix.mdc");
64062
64372
  case "codex":
64063
- return path20.join(home, ".codex", "AGENTS.md");
64373
+ return path21.join(home, ".codex", "AGENTS.md");
64064
64374
  case "opencode":
64065
- return path20.join(home, ".opencode", "AGENTS.md");
64375
+ return path21.join(home, ".opencode", "AGENTS.md");
64066
64376
  case "antigravity":
64067
- return path20.join(home, ".gemini", "GEMINI.md");
64377
+ return path21.join(home, ".gemini", "GEMINI.md");
64068
64378
  case "trae":
64069
- return path20.join(home, ".trae", "rules", "project_rules.md");
64379
+ return path21.join(home, ".trae", "rules", "project_rules.md");
64070
64380
  default:
64071
64381
  return "";
64072
64382
  }
64073
64383
  } else {
64074
64384
  switch (agent) {
64075
64385
  case "cursor":
64076
- return path20.join(cwd, ".cursor", "rules", "memorix.mdc");
64386
+ return path21.join(cwd, ".cursor", "rules", "memorix.mdc");
64077
64387
  case "codex":
64078
- return path20.join(cwd, ".codex", "AGENTS.md");
64388
+ return path21.join(cwd, ".codex", "AGENTS.md");
64079
64389
  case "opencode":
64080
- return path20.join(cwd, ".opencode", "AGENTS.md");
64390
+ return path21.join(cwd, ".opencode", "AGENTS.md");
64081
64391
  case "antigravity":
64082
- return path20.join(cwd, ".gemini", "GEMINI.md");
64392
+ return path21.join(cwd, ".gemini", "GEMINI.md");
64083
64393
  case "trae":
64084
- return path20.join(cwd, ".trae", "rules", "project_rules.md");
64394
+ return path21.join(cwd, ".trae", "rules", "project_rules.md");
64085
64395
  default:
64086
64396
  return "";
64087
64397
  }
@@ -64170,10 +64480,10 @@ var init_hooks_preview = __esm({
64170
64480
  }
64171
64481
  }
64172
64482
  if (agent === "kiro") {
64173
- const hooksDir = path20.dirname(configPath);
64483
+ const hooksDir = path21.dirname(configPath);
64174
64484
  previewItems.push({
64175
64485
  agent,
64176
- path: path20.join(hooksDir, "*.kiro.hook"),
64486
+ path: path21.join(hooksDir, "*.kiro.hook"),
64177
64487
  action: "create",
64178
64488
  size: "~500B each"
64179
64489
  });
@@ -64931,10 +65241,10 @@ var ingest_image_exports = {};
64931
65241
  __export(ingest_image_exports, {
64932
65242
  default: () => ingest_image_default
64933
65243
  });
64934
- import { readFileSync as readFileSync10 } from "fs";
64935
- import path21 from "path";
65244
+ import { readFileSync as readFileSync11 } from "fs";
65245
+ import path22 from "path";
64936
65246
  function inferMimeType(filePath) {
64937
- const ext = path21.extname(filePath).toLowerCase();
65247
+ const ext = path22.extname(filePath).toLowerCase();
64938
65248
  switch (ext) {
64939
65249
  case ".jpg":
64940
65250
  case ".jpeg":
@@ -64976,9 +65286,9 @@ var init_ingest_image = __esm({
64976
65286
  return;
64977
65287
  }
64978
65288
  const { project } = await getCliProjectContext();
64979
- const resolvedPath = path21.resolve(process.cwd(), imagePath);
64980
- const base642 = readFileSync10(resolvedPath).toString("base64");
64981
- const filename = path21.basename(resolvedPath);
65289
+ const resolvedPath = path22.resolve(process.cwd(), imagePath);
65290
+ const base642 = readFileSync11(resolvedPath).toString("base64");
65291
+ const filename = path22.basename(resolvedPath);
64982
65292
  const analysis = await analyzeImage({
64983
65293
  base64: base642,
64984
65294
  filename,
@@ -65062,7 +65372,7 @@ var git_hook_install_exports = {};
65062
65372
  __export(git_hook_install_exports, {
65063
65373
  default: () => git_hook_install_default
65064
65374
  });
65065
- import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync4, chmodSync } from "fs";
65375
+ import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync4, chmodSync } from "fs";
65066
65376
  function generateHookScript() {
65067
65377
  return `${HOOK_MARKER}
65068
65378
  # Memorix: Auto-ingest git commits as memories
@@ -65109,8 +65419,8 @@ var init_git_hook_install = __esm({
65109
65419
  return;
65110
65420
  }
65111
65421
  const { hookPath } = resolved;
65112
- if (existsSync11(hookPath)) {
65113
- const existing = readFileSync11(hookPath, "utf-8");
65422
+ if (existsSync12(hookPath)) {
65423
+ const existing = readFileSync12(hookPath, "utf-8");
65114
65424
  if (existing.includes(HOOK_MARKER)) {
65115
65425
  v3.warn("Memorix git hook is already installed.");
65116
65426
  fe2("Use `memorix git-hook uninstall` to remove it first.");
@@ -65159,7 +65469,7 @@ var git_hook_uninstall_exports = {};
65159
65469
  __export(git_hook_uninstall_exports, {
65160
65470
  default: () => git_hook_uninstall_default
65161
65471
  });
65162
- import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync5, unlinkSync as unlinkSync2 } from "fs";
65472
+ import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync5, unlinkSync as unlinkSync2 } from "fs";
65163
65473
  var HOOK_MARKER2, git_hook_uninstall_default;
65164
65474
  var init_git_hook_uninstall = __esm({
65165
65475
  "src/cli/commands/git-hook-uninstall.ts"() {
@@ -65191,12 +65501,12 @@ var init_git_hook_uninstall = __esm({
65191
65501
  return;
65192
65502
  }
65193
65503
  const { hookPath } = resolved;
65194
- if (!existsSync12(hookPath)) {
65504
+ if (!existsSync13(hookPath)) {
65195
65505
  v3.warn("No post-commit hook found.");
65196
65506
  fe2("Nothing to uninstall.");
65197
65507
  return;
65198
65508
  }
65199
- const content = readFileSync12(hookPath, "utf-8");
65509
+ const content = readFileSync13(hookPath, "utf-8");
65200
65510
  if (!content.includes(HOOK_MARKER2)) {
65201
65511
  v3.warn("Post-commit hook exists but does not contain memorix hook.");
65202
65512
  fe2("Nothing to uninstall.");
@@ -65777,10 +66087,15 @@ var init_doctor = __esm({
65777
66087
  type: "boolean",
65778
66088
  description: "Output as JSON instead of human-readable text",
65779
66089
  default: false
66090
+ },
66091
+ receipt: {
66092
+ type: "boolean",
66093
+ description: "Include privacy-safe memory handoff receipt",
66094
+ default: false
65780
66095
  }
65781
66096
  },
65782
66097
  run: async ({ args }) => {
65783
- const { existsSync: existsSync18, readFileSync: readFileSync17 } = await import("fs");
66098
+ const { existsSync: existsSync19, readFileSync: readFileSync18 } = await import("fs");
65784
66099
  const { join: join29, basename: basename4 } = await import("path");
65785
66100
  const { homedir: homedir25 } = await import("os");
65786
66101
  const { execSync: execSync10 } = await import("child_process");
@@ -65849,8 +66164,8 @@ var init_doctor = __esm({
65849
66164
  let bgPort = 0;
65850
66165
  let bgPid = 0;
65851
66166
  try {
65852
- if (existsSync18(bgStatePath)) {
65853
- const bgState = JSON.parse(readFileSync17(bgStatePath, "utf-8"));
66167
+ if (existsSync19(bgStatePath)) {
66168
+ const bgState = JSON.parse(readFileSync18(bgStatePath, "utf-8"));
65854
66169
  bgPid = bgState.pid;
65855
66170
  bgPort = bgState.port;
65856
66171
  try {
@@ -65942,8 +66257,8 @@ var init_doctor = __esm({
65942
66257
  }
65943
66258
  try {
65944
66259
  const cachePath = join29(memorixDir, "embedding-cache.json");
65945
- if (existsSync18(cachePath)) {
65946
- const cache4 = JSON.parse(readFileSync17(cachePath, "utf-8"));
66260
+ if (existsSync19(cachePath)) {
66261
+ const cache4 = JSON.parse(readFileSync18(cachePath, "utf-8"));
65947
66262
  const cacheCount = Object.keys(cache4).length;
65948
66263
  lines.push(info(`Cached embeddings: ${cacheCount}`));
65949
66264
  report.embedding.cachedEmbeddings = cacheCount;
@@ -65957,7 +66272,7 @@ var init_doctor = __esm({
65957
66272
  }
65958
66273
  lines.push("");
65959
66274
  lines.push("\u250C\u2500 Data Status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
65960
- if (dataDir && existsSync18(dataDir)) {
66275
+ if (dataDir && existsSync19(dataDir)) {
65961
66276
  let obsCount = 0;
65962
66277
  let activeCount = 0;
65963
66278
  let ranCount = 0;
@@ -66021,9 +66336,9 @@ var init_doctor = __esm({
66021
66336
  let conflictsFound = false;
66022
66337
  if (dataDir) {
66023
66338
  const lockFile = join29(dataDir, ".memorix.lock");
66024
- if (existsSync18(lockFile)) {
66339
+ if (existsSync19(lockFile)) {
66025
66340
  try {
66026
- const lockData = JSON.parse(readFileSync17(lockFile, "utf-8"));
66341
+ const lockData = JSON.parse(readFileSync18(lockFile, "utf-8"));
66027
66342
  const lockAge = Date.now() - lockData.time;
66028
66343
  if (lockAge < 1e4) {
66029
66344
  lines.push(warn(`Active file lock (PID ${lockData.pid}, age ${Math.round(lockAge / 1e3)}s)`));
@@ -66080,15 +66395,32 @@ var init_doctor = __esm({
66080
66395
  } else {
66081
66396
  lines.push(info("No update checks recorded yet"));
66082
66397
  }
66083
- const autoEnabled = !["off", "false", "0", "notify"].includes(
66084
- (process.env.MEMORIX_AUTO_UPDATE ?? "").toLowerCase().trim()
66085
- );
66086
- lines.push(info(`Auto-update: ${autoEnabled ? "enabled (install)" : "disabled"}`));
66087
- report.autoUpdate = { enabled: autoEnabled, currentVersion: curVer, cache: cache4 };
66398
+ const modeRaw = (process.env.MEMORIX_AUTO_UPDATE ?? "").toLowerCase().trim();
66399
+ const autoUpdateMode = !modeRaw || modeRaw === "notify" ? "notify" : ["off", "false", "0"].includes(modeRaw) ? "off" : ["install", "true", "1"].includes(modeRaw) ? "install" : "notify";
66400
+ lines.push(info(
66401
+ autoUpdateMode === "off" ? "Auto-update: disabled" : autoUpdateMode === "install" ? "Auto-update: enabled (background install)" : "Auto-update: enabled (notify only)"
66402
+ ));
66403
+ report.autoUpdate = { enabled: autoUpdateMode !== "off", mode: autoUpdateMode, currentVersion: curVer, cache: cache4 };
66088
66404
  } catch {
66089
66405
  lines.push(info("Auto-update status unavailable"));
66090
66406
  report.autoUpdate = { enabled: false };
66091
66407
  }
66408
+ if (args.receipt && projectId) {
66409
+ lines.push("");
66410
+ lines.push("\u250C\u2500 Memory Handoff Receipt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
66411
+ try {
66412
+ const { buildHandoffReceipt: buildHandoffReceipt2 } = await Promise.resolve().then(() => (init_receipt_service(), receipt_service_exports));
66413
+ const receipt = await buildHandoffReceipt2({ cwd: projectRoot || process.cwd(), transport: "cli" });
66414
+ lines.push(ok(`Project identity: ${receipt["project.identity_hash"]}`));
66415
+ lines.push(ok(`Stored memories: ${receipt["memory.write.count"]}`));
66416
+ lines.push(info(String(receipt.boundary)));
66417
+ report.receipt = receipt;
66418
+ } catch (e3) {
66419
+ const message = e3 instanceof Error ? e3.message : String(e3);
66420
+ lines.push(warn(`Receipt unavailable: ${message}`));
66421
+ report.receipt = { error: message };
66422
+ }
66423
+ }
66092
66424
  lines.push("");
66093
66425
  lines.push("\u250C\u2500 Summary \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
66094
66426
  if (issues.length === 0) {
@@ -66125,7 +66457,7 @@ __export(dashboard_exports, {
66125
66457
  default: () => dashboard_default
66126
66458
  });
66127
66459
  import { fileURLToPath as fileURLToPath2 } from "url";
66128
- import path22 from "path";
66460
+ import path23 from "path";
66129
66461
  var dashboard_default;
66130
66462
  var init_dashboard = __esm({
66131
66463
  "src/cli/commands/dashboard.ts"() {
@@ -66155,8 +66487,8 @@ var init_dashboard = __esm({
66155
66487
  }
66156
66488
  const dataDir = await getProjectDataDir2(project.id);
66157
66489
  const port = parseInt(args.port, 10) || 3210;
66158
- const cliDir = path22.dirname(fileURLToPath2(import.meta.url));
66159
- const staticDir = path22.join(cliDir, "..", "dashboard", "static");
66490
+ const cliDir = path23.dirname(fileURLToPath2(import.meta.url));
66491
+ const staticDir = path23.join(cliDir, "..", "dashboard", "static");
66160
66492
  await startDashboard2(dataDir, port, staticDir, project.id, project.name, true, void 0, project.rootPath, true);
66161
66493
  await new Promise(() => {
66162
66494
  });
@@ -66393,7 +66725,7 @@ __export(uninstall_exports, {
66393
66725
  default: () => uninstall_default
66394
66726
  });
66395
66727
  import * as fs17 from "fs";
66396
- import * as path23 from "path";
66728
+ import * as path24 from "path";
66397
66729
  import * as os4 from "os";
66398
66730
  function exists(p2) {
66399
66731
  try {
@@ -66427,100 +66759,100 @@ function getMCPConfigEntries(home, cwd) {
66427
66759
  const entries = [];
66428
66760
  entries.push({
66429
66761
  agent: "Claude Code",
66430
- path: path23.join(home, ".claude.json"),
66762
+ path: path24.join(home, ".claude.json"),
66431
66763
  kind: "global",
66432
66764
  format: "json",
66433
- detected: checkJSON(path23.join(home, ".claude.json")),
66765
+ detected: checkJSON(path24.join(home, ".claude.json")),
66434
66766
  note: 'Remove the "memorix" key from mcpServers in this file.'
66435
66767
  });
66436
66768
  entries.push({
66437
66769
  agent: "Claude Code",
66438
- path: path23.join(cwd, ".claude", "settings.json"),
66770
+ path: path24.join(cwd, ".claude", "settings.json"),
66439
66771
  kind: "project",
66440
66772
  format: "json",
66441
- detected: checkJSON(path23.join(cwd, ".claude", "settings.json")),
66773
+ detected: checkJSON(path24.join(cwd, ".claude", "settings.json")),
66442
66774
  note: 'Remove the "memorix" key from mcpServers in this file.'
66443
66775
  });
66444
66776
  entries.push({
66445
66777
  agent: "Cursor",
66446
- path: path23.join(home, ".cursor", "mcp.json"),
66778
+ path: path24.join(home, ".cursor", "mcp.json"),
66447
66779
  kind: "global",
66448
66780
  format: "json",
66449
- detected: checkJSON(path23.join(home, ".cursor", "mcp.json")),
66781
+ detected: checkJSON(path24.join(home, ".cursor", "mcp.json")),
66450
66782
  note: 'Remove the "memorix" key from mcpServers in this file.'
66451
66783
  });
66452
66784
  entries.push({
66453
66785
  agent: "Cursor",
66454
- path: path23.join(cwd, ".cursor", "mcp.json"),
66786
+ path: path24.join(cwd, ".cursor", "mcp.json"),
66455
66787
  kind: "project",
66456
66788
  format: "json",
66457
- detected: checkJSON(path23.join(cwd, ".cursor", "mcp.json")),
66789
+ detected: checkJSON(path24.join(cwd, ".cursor", "mcp.json")),
66458
66790
  note: 'Remove the "memorix" key from mcpServers in this file.'
66459
66791
  });
66460
66792
  entries.push({
66461
66793
  agent: "Windsurf",
66462
- path: path23.join(home, ".codeium", "windsurf", "mcp_config.json"),
66794
+ path: path24.join(home, ".codeium", "windsurf", "mcp_config.json"),
66463
66795
  kind: "global",
66464
66796
  format: "json",
66465
- detected: checkJSON(path23.join(home, ".codeium", "windsurf", "mcp_config.json")),
66797
+ detected: checkJSON(path24.join(home, ".codeium", "windsurf", "mcp_config.json")),
66466
66798
  note: 'Remove the "memorix" key from mcpServers in this file.'
66467
66799
  });
66468
66800
  entries.push({
66469
66801
  agent: "Codex",
66470
- path: path23.join(home, ".codex", "config.toml"),
66802
+ path: path24.join(home, ".codex", "config.toml"),
66471
66803
  kind: "global",
66472
66804
  format: "toml",
66473
- detected: checkTOML(path23.join(home, ".codex", "config.toml")),
66805
+ detected: checkTOML(path24.join(home, ".codex", "config.toml")),
66474
66806
  note: "Remove the [mcp_servers.memorix] section from this file."
66475
66807
  });
66476
66808
  entries.push({
66477
66809
  agent: "VS Code / Copilot",
66478
- path: path23.join(home, ".vscode", "mcp.json"),
66810
+ path: path24.join(home, ".vscode", "mcp.json"),
66479
66811
  kind: "global",
66480
66812
  format: "json",
66481
- detected: checkJSON(path23.join(home, ".vscode", "mcp.json")),
66813
+ detected: checkJSON(path24.join(home, ".vscode", "mcp.json")),
66482
66814
  note: 'Remove the "memorix" key from servers in this file.'
66483
66815
  });
66484
66816
  entries.push({
66485
66817
  agent: "VS Code / Copilot",
66486
- path: path23.join(cwd, ".vscode", "mcp.json"),
66818
+ path: path24.join(cwd, ".vscode", "mcp.json"),
66487
66819
  kind: "project",
66488
66820
  format: "json",
66489
- detected: checkJSON(path23.join(cwd, ".vscode", "mcp.json")),
66821
+ detected: checkJSON(path24.join(cwd, ".vscode", "mcp.json")),
66490
66822
  note: 'Remove the "memorix" key from servers in this file.'
66491
66823
  });
66492
66824
  entries.push({
66493
66825
  agent: "Kiro",
66494
- path: path23.join(home, ".kiro", "settings", "mcp.json"),
66826
+ path: path24.join(home, ".kiro", "settings", "mcp.json"),
66495
66827
  kind: "global",
66496
66828
  format: "json",
66497
- detected: checkJSON(path23.join(home, ".kiro", "settings", "mcp.json")),
66829
+ detected: checkJSON(path24.join(home, ".kiro", "settings", "mcp.json")),
66498
66830
  note: 'Remove the "memorix" key from mcpServers in this file.'
66499
66831
  });
66500
66832
  entries.push({
66501
66833
  agent: "Kiro",
66502
- path: path23.join(cwd, ".kiro", "settings", "mcp.json"),
66834
+ path: path24.join(cwd, ".kiro", "settings", "mcp.json"),
66503
66835
  kind: "project",
66504
66836
  format: "json",
66505
- detected: checkJSON(path23.join(cwd, ".kiro", "settings", "mcp.json")),
66837
+ detected: checkJSON(path24.join(cwd, ".kiro", "settings", "mcp.json")),
66506
66838
  note: 'Remove the "memorix" key from mcpServers in this file.'
66507
66839
  });
66508
66840
  entries.push({
66509
66841
  agent: "Gemini CLI / Antigravity",
66510
- path: path23.join(home, ".gemini", "settings.json"),
66842
+ path: path24.join(home, ".gemini", "settings.json"),
66511
66843
  kind: "global",
66512
66844
  format: "json",
66513
- detected: checkJSON(path23.join(home, ".gemini", "settings.json")),
66845
+ detected: checkJSON(path24.join(home, ".gemini", "settings.json")),
66514
66846
  note: 'Remove the "memorix" key from mcpServers in this file.'
66515
66847
  });
66516
66848
  const traeCfg = (() => {
66517
66849
  if (process.platform === "win32") {
66518
- return path23.join(process.env.APPDATA || path23.join(home, "AppData", "Roaming"), "Trae", "User", "mcp.json");
66850
+ return path24.join(process.env.APPDATA || path24.join(home, "AppData", "Roaming"), "Trae", "User", "mcp.json");
66519
66851
  }
66520
66852
  if (process.platform === "darwin") {
66521
- return path23.join(home, "Library", "Application Support", "Trae", "User", "mcp.json");
66853
+ return path24.join(home, "Library", "Application Support", "Trae", "User", "mcp.json");
66522
66854
  }
66523
- return path23.join(home, ".config", "Trae", "User", "mcp.json");
66855
+ return path24.join(home, ".config", "Trae", "User", "mcp.json");
66524
66856
  })();
66525
66857
  entries.push({
66526
66858
  agent: "Trae",
@@ -66533,7 +66865,7 @@ function getMCPConfigEntries(home, cwd) {
66533
66865
  return entries;
66534
66866
  }
66535
66867
  function checkBackground(home) {
66536
- const statePath = path23.join(home, ".memorix", "background.json");
66868
+ const statePath = path24.join(home, ".memorix", "background.json");
66537
66869
  try {
66538
66870
  const data = fs17.readFileSync(statePath, "utf-8");
66539
66871
  const state = JSON.parse(data);
@@ -66674,7 +67006,7 @@ var init_uninstall = __esm({
66674
67006
  },
66675
67007
  async run({ args }) {
66676
67008
  const home = os4.homedir();
66677
- const memorixDir = path23.join(home, ".memorix");
67009
+ const memorixDir = path24.join(home, ".memorix");
66678
67010
  const dryRun = args["dry-run"];
66679
67011
  const yes = args.yes;
66680
67012
  const doHooks = args.hooks;
@@ -67173,14 +67505,14 @@ var init_claude_stream = __esm({
67173
67505
 
67174
67506
  // src/orchestrate/adapters/claude.ts
67175
67507
  import * as fs18 from "fs";
67176
- import * as path24 from "path";
67508
+ import * as path25 from "path";
67177
67509
  function resolveMcpConfigPath(projectDir2) {
67178
- const localPath = path24.join(projectDir2, ".claude", "settings.local.json");
67510
+ const localPath = path25.join(projectDir2, ".claude", "settings.local.json");
67179
67511
  try {
67180
67512
  if (fs18.existsSync(localPath)) return localPath;
67181
67513
  } catch {
67182
67514
  }
67183
- const settingsPath = path24.join(projectDir2, ".claude", "settings.json");
67515
+ const settingsPath = path25.join(projectDir2, ".claude", "settings.json");
67184
67516
  try {
67185
67517
  if (fs18.existsSync(settingsPath)) return settingsPath;
67186
67518
  } catch {
@@ -67189,7 +67521,7 @@ function resolveMcpConfigPath(projectDir2) {
67189
67521
  mcpServers: {
67190
67522
  memorix: {
67191
67523
  command: process.execPath,
67192
- args: [path24.resolve(path24.dirname(process.execPath), "..", "lib", "node_modules", "memorix", "dist", "index.js"), "serve", "--transport", "stdio"]
67524
+ args: [path25.resolve(path25.dirname(process.execPath), "..", "lib", "node_modules", "memorix", "dist", "index.js"), "serve", "--transport", "stdio"]
67193
67525
  }
67194
67526
  }
67195
67527
  };
@@ -67199,9 +67531,9 @@ function resolveMcpConfigPath(projectDir2) {
67199
67531
  args: ["serve", "--transport", "stdio"]
67200
67532
  };
67201
67533
  try {
67202
- const claudeDir = path24.join(projectDir2, ".claude");
67534
+ const claudeDir = path25.join(projectDir2, ".claude");
67203
67535
  fs18.mkdirSync(claudeDir, { recursive: true });
67204
- const tempPath = path24.join(claudeDir, "settings.local.json");
67536
+ const tempPath = path25.join(claudeDir, "settings.local.json");
67205
67537
  fs18.writeFileSync(tempPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
67206
67538
  return tempPath;
67207
67539
  } catch {
@@ -68031,7 +68363,7 @@ var init_pipeline_trace = __esm({
68031
68363
 
68032
68364
  // src/orchestrate/worktree.ts
68033
68365
  import { execSync as execSync7 } from "child_process";
68034
- import { existsSync as existsSync15, rmSync as rmSync2 } from "fs";
68366
+ import { existsSync as existsSync16, rmSync as rmSync2 } from "fs";
68035
68367
  import { join as join27, basename as basename3 } from "path";
68036
68368
  function createWorktree(projectDir2, taskId, pipelineId) {
68037
68369
  const shortId2 = taskId.slice(0, 8);
@@ -68092,7 +68424,7 @@ function removeWorktree(projectDir2, worktreePath, branch) {
68092
68424
  timeout: 1e4
68093
68425
  });
68094
68426
  } catch {
68095
- if (existsSync15(worktreePath)) {
68427
+ if (existsSync16(worktreePath)) {
68096
68428
  try {
68097
68429
  rmSync2(worktreePath, { recursive: true, force: true });
68098
68430
  } catch {
@@ -68590,9 +68922,9 @@ function writePipelineSummary(projectDir2, summary) {
68590
68922
  return null;
68591
68923
  }
68592
68924
  }
68593
- function safeWrite(path25, content) {
68925
+ function safeWrite(path26, content) {
68594
68926
  try {
68595
- writeFileSync8(path25, content, "utf-8");
68927
+ writeFileSync8(path26, content, "utf-8");
68596
68928
  } catch {
68597
68929
  }
68598
68930
  }
@@ -68722,7 +69054,7 @@ var init_permission = __esm({
68722
69054
  });
68723
69055
 
68724
69056
  // src/orchestrate/memorix-bridge.ts
68725
- import { createHash as createHash5 } from "crypto";
69057
+ import { createHash as createHash6 } from "crypto";
68726
69058
  async function getStoreObservation() {
68727
69059
  if (!_storeObservation) {
68728
69060
  const mod = await Promise.resolve().then(() => (init_observations(), observations_exports));
@@ -68860,7 +69192,7 @@ function sanitizeErrorPattern(text) {
68860
69192
  }
68861
69193
  function hashErrorPattern(errorOutput) {
68862
69194
  const sanitized = sanitizeErrorPattern(errorOutput).slice(0, 500);
68863
- return createHash5("sha256").update(sanitized).digest("hex").slice(0, 12);
69195
+ return createHash6("sha256").update(sanitized).digest("hex").slice(0, 12);
68864
69196
  }
68865
69197
  function sleep2(ms) {
68866
69198
  return new Promise((resolve2) => setTimeout(() => resolve2([]), ms));
@@ -69965,8 +70297,8 @@ var init_orchestrate = __esm({
69965
70297
  const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
69966
70298
  const { resolveAdapters: resolveAdapters2, parseAgentQuotas: parseAgentQuotas2, buildQuotaMap: buildQuotaMap2 } = await Promise.resolve().then(() => (init_adapters(), adapters_exports));
69967
70299
  const { runCoordinationLoop: runCoordinationLoop2 } = await Promise.resolve().then(() => (init_coordinator(), coordinator_exports));
69968
- const path25 = await import("path");
69969
- const projectDir2 = args.project ? path25.resolve(args.project) : process.cwd();
70300
+ const path26 = await import("path");
70301
+ const projectDir2 = args.project ? path26.resolve(args.project) : process.cwd();
69970
70302
  const proj = detectProject2(projectDir2);
69971
70303
  if (!proj) {
69972
70304
  console.error("[ERROR] Not a git repository. Run `git init` first.");
@@ -73901,14 +74233,14 @@ function WorkbenchApp({ version: version2, onExitForInteractive }) {
73901
74233
  }
73902
74234
  try {
73903
74235
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
73904
- const { existsSync: existsSync18, readFileSync: readFileSync17, writeFileSync: writeFileSync10, unlinkSync: unlinkSync4 } = await import("fs");
74236
+ const { existsSync: existsSync19, readFileSync: readFileSync18, writeFileSync: writeFileSync10, unlinkSync: unlinkSync4 } = await import("fs");
73905
74237
  const resolved = resolveHooksDir2(proj.rootPath);
73906
74238
  const hookMarker = "# [memorix-git-hook]";
73907
- if (!resolved || !existsSync18(resolved.hookPath)) {
74239
+ if (!resolved || !existsSync19(resolved.hookPath)) {
73908
74240
  setActionStatus("No post-commit hook found.");
73909
74241
  return;
73910
74242
  }
73911
- const content = readFileSync17(resolved.hookPath, "utf-8");
74243
+ const content = readFileSync18(resolved.hookPath, "utf-8");
73912
74244
  if (!content.includes(hookMarker)) {
73913
74245
  setActionStatus("No memorix hook installed.");
73914
74246
  return;
@@ -74059,7 +74391,7 @@ function WorkbenchApp({ version: version2, onExitForInteractive }) {
74059
74391
  break;
74060
74392
  }
74061
74393
  case "3": {
74062
- const { existsSync: existsSync18, readFileSync: readFileSync17, writeFileSync: writeFileSync10, chmodSync: chmodSync2 } = await import("fs");
74394
+ const { existsSync: existsSync19, readFileSync: readFileSync18, writeFileSync: writeFileSync10, chmodSync: chmodSync2 } = await import("fs");
74063
74395
  const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
74064
74396
  const hookMarker = "# [memorix-git-hook]";
74065
74397
  const resolved = ensureHooksDir2(cwd);
@@ -74073,12 +74405,12 @@ if command -v memorix >/dev/null 2>&1; then
74073
74405
  memorix ingest commit --auto >/dev/null 2>&1 &
74074
74406
  fi
74075
74407
  `;
74076
- if (existsSync18(resolved.hookPath)) {
74077
- if (readFileSync17(resolved.hookPath, "utf-8").includes(hookMarker)) {
74408
+ if (existsSync19(resolved.hookPath)) {
74409
+ if (readFileSync18(resolved.hookPath, "utf-8").includes(hookMarker)) {
74078
74410
  setActionStatus("Post-commit hook already installed.");
74079
74411
  break;
74080
74412
  }
74081
- writeFileSync10(resolved.hookPath, `${readFileSync17(resolved.hookPath, "utf-8").trimEnd()}
74413
+ writeFileSync10(resolved.hookPath, `${readFileSync18(resolved.hookPath, "utf-8").trimEnd()}
74082
74414
 
74083
74415
  ${hookScript}`, "utf-8");
74084
74416
  } else {
@@ -74093,15 +74425,15 @@ ${hookScript}`, "utf-8");
74093
74425
  break;
74094
74426
  }
74095
74427
  case "4": {
74096
- const { existsSync: existsSync18, readFileSync: readFileSync17, writeFileSync: writeFileSync10, unlinkSync: unlinkSync4 } = await import("fs");
74428
+ const { existsSync: existsSync19, readFileSync: readFileSync18, writeFileSync: writeFileSync10, unlinkSync: unlinkSync4 } = await import("fs");
74097
74429
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
74098
74430
  const hookMarker = "# [memorix-git-hook]";
74099
74431
  const resolved = resolveHooksDir2(cwd);
74100
- if (!resolved || !existsSync18(resolved.hookPath)) {
74432
+ if (!resolved || !existsSync19(resolved.hookPath)) {
74101
74433
  setActionStatus("No post-commit hook found.");
74102
74434
  break;
74103
74435
  }
74104
- const content = readFileSync17(resolved.hookPath, "utf-8");
74436
+ const content = readFileSync18(resolved.hookPath, "utf-8");
74105
74437
  if (!content.includes(hookMarker)) {
74106
74438
  setActionStatus("No memorix hook installed.");
74107
74439
  break;
@@ -74833,6 +75165,7 @@ var main = defineCommand({
74833
75165
  lock: () => Promise.resolve().then(() => (init_lock(), lock_exports)).then((m4) => m4.default),
74834
75166
  handoff: () => Promise.resolve().then(() => (init_handoff2(), handoff_exports2)).then((m4) => m4.default),
74835
75167
  poll: () => Promise.resolve().then(() => (init_poll2(), poll_exports2)).then((m4) => m4.default),
75168
+ receipt: () => Promise.resolve().then(() => (init_receipt(), receipt_exports)).then((m4) => m4.default),
74836
75169
  serve: () => Promise.resolve().then(() => (init_serve(), serve_exports)).then((m4) => m4.default),
74837
75170
  "serve-http": () => Promise.resolve().then(() => (init_serve_http(), serve_http_exports)).then((m4) => m4.default),
74838
75171
  status: () => Promise.resolve().then(() => (init_status(), status_exports)).then((m4) => m4.default),
@@ -74882,6 +75215,7 @@ var main = defineCommand({
74882
75215
  "lock",
74883
75216
  "handoff",
74884
75217
  "poll",
75218
+ "receipt",
74885
75219
  "serve",
74886
75220
  "serve-http",
74887
75221
  "status",
@@ -74928,6 +75262,7 @@ var main = defineCommand({
74928
75262
  console.error(" lock Manage advisory file locks");
74929
75263
  console.error(" handoff Create durable handoff artifacts");
74930
75264
  console.error(" poll Snapshot project coordination state");
75265
+ console.error(" receipt Privacy-safe memory handoff diagnostic");
74931
75266
  console.error(" serve-http Start HTTP MCP + dashboard control plane");
74932
75267
  console.error(" serve Start MCP server on stdio");
74933
75268
  console.error(" init Create global defaults or project config");