memorix 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/CLAUDE.md +6 -1
  3. package/README.md +21 -0
  4. package/README.zh-CN.md +21 -0
  5. package/TEAM.md +86 -86
  6. package/dist/cli/index.js +852 -214
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/dashboard/static/index.html +201 -201
  9. package/dist/dashboard/static/style.css +3584 -3584
  10. package/dist/index.js +129 -62
  11. package/dist/index.js.map +1 -1
  12. package/dist/memcode-runtime/CHANGELOG.md +22 -0
  13. package/dist/memcode-runtime/package.json +4 -4
  14. package/dist/sdk.js +129 -62
  15. package/dist/sdk.js.map +1 -1
  16. package/docs/AGENT_OPERATOR_PLAYBOOK.md +18 -0
  17. package/docs/API_REFERENCE.md +2 -0
  18. package/docs/CONFIGURATION.md +18 -0
  19. package/docs/DESIGN_DECISIONS.md +357 -357
  20. package/docs/SETUP.md +10 -0
  21. package/docs/dev-log/progress.txt +23 -30
  22. package/package.json +1 -1
  23. package/src/audit/index.ts +156 -156
  24. package/src/cli/commands/agent-integrations.ts +623 -0
  25. package/src/cli/commands/audit-list.ts +89 -89
  26. package/src/cli/commands/background.ts +659 -659
  27. package/src/cli/commands/cleanup.ts +255 -255
  28. package/src/cli/commands/codegraph.ts +4 -0
  29. package/src/cli/commands/config-get.ts +9 -2
  30. package/src/cli/commands/doctor.ts +26 -0
  31. package/src/cli/commands/formation.ts +48 -48
  32. package/src/cli/commands/git-hook-install.ts +111 -111
  33. package/src/cli/commands/handoff.ts +66 -66
  34. package/src/cli/commands/hooks-status.ts +63 -63
  35. package/src/cli/commands/ingest-commit.ts +153 -153
  36. package/src/cli/commands/ingest-image.ts +73 -73
  37. package/src/cli/commands/ingest-log.ts +180 -180
  38. package/src/cli/commands/ingest.ts +44 -44
  39. package/src/cli/commands/integrate-shared.ts +15 -15
  40. package/src/cli/commands/lock.ts +96 -96
  41. package/src/cli/commands/message.ts +121 -121
  42. package/src/cli/commands/poll.ts +70 -70
  43. package/src/cli/commands/purge-all-memory.ts +85 -85
  44. package/src/cli/commands/purge-project-memory.ts +83 -83
  45. package/src/cli/commands/reasoning.ts +132 -132
  46. package/src/cli/commands/repair.ts +60 -0
  47. package/src/cli/commands/retention.ts +108 -108
  48. package/src/cli/commands/serve-shared.ts +118 -118
  49. package/src/cli/commands/setup.ts +3 -3
  50. package/src/cli/commands/skills.ts +123 -123
  51. package/src/cli/commands/task.ts +192 -192
  52. package/src/cli/commands/transfer.ts +73 -73
  53. package/src/cli/commands/uninstall-project-artifacts.ts +85 -85
  54. package/src/cli/index.ts +3 -1
  55. package/src/cli/tui/ChatView.tsx +234 -234
  56. package/src/cli/tui/CommandBar.tsx +312 -312
  57. package/src/cli/tui/ContextRail.tsx +118 -118
  58. package/src/cli/tui/HeaderBar.tsx +72 -72
  59. package/src/cli/tui/LogoBanner.tsx +51 -51
  60. package/src/cli/tui/Panels.tsx +632 -632
  61. package/src/cli/tui/Sidebar.tsx +179 -179
  62. package/src/cli/tui/chat-service.ts +742 -742
  63. package/src/cli/tui/data.ts +547 -547
  64. package/src/cli/tui/index.ts +41 -41
  65. package/src/cli/tui/markdown-render.tsx +371 -371
  66. package/src/cli/tui/theme.ts +178 -178
  67. package/src/cli/tui/use-mouse.ts +157 -157
  68. package/src/cli/tui/useNavigation.ts +56 -56
  69. package/src/cli/update-checker.ts +211 -211
  70. package/src/cli/version.ts +7 -7
  71. package/src/cli/workbench.ts +1 -1
  72. package/src/codegraph/auto-context.ts +6 -0
  73. package/src/codegraph/context-pack.ts +7 -6
  74. package/src/codegraph/exclude.ts +47 -0
  75. package/src/codegraph/lite-provider.ts +5 -24
  76. package/src/codegraph/project-context.ts +13 -15
  77. package/src/compact/token-budget.ts +74 -74
  78. package/src/config/behavior.ts +59 -59
  79. package/src/config/resolved-config.ts +6 -0
  80. package/src/config/toml-loader.ts +4 -0
  81. package/src/config/yaml-loader.ts +7 -0
  82. package/src/dashboard/project-classification.ts +64 -64
  83. package/src/dashboard/static/index.html +201 -201
  84. package/src/dashboard/static/style.css +3584 -3584
  85. package/src/embedding/fastembed-provider.ts +142 -142
  86. package/src/embedding/transformers-provider.ts +111 -111
  87. package/src/git/extractor.ts +209 -209
  88. package/src/git/hooks-path.ts +85 -85
  89. package/src/git/noise-filter.ts +210 -210
  90. package/src/hooks/installers/index.ts +4 -4
  91. package/src/hooks/official-skills.ts +1 -1
  92. package/src/hooks/pattern-detector.ts +173 -173
  93. package/src/hooks/rules/memorix-agent-rules.md +2 -2
  94. package/src/hooks/significance-filter.ts +250 -250
  95. package/src/llm/memory-manager.ts +328 -328
  96. package/src/llm/provider.ts +885 -885
  97. package/src/llm/quality.ts +248 -248
  98. package/src/memory/attribution-guard.ts +249 -249
  99. package/src/memory/auto-relations.ts +107 -107
  100. package/src/memory/consolidation.ts +302 -302
  101. package/src/memory/disclosure-policy.ts +141 -141
  102. package/src/memory/entity-extractor.ts +197 -197
  103. package/src/memory/formation/evaluate.ts +217 -217
  104. package/src/memory/formation/extract.ts +361 -361
  105. package/src/memory/formation/index.ts +417 -417
  106. package/src/memory/formation/resolve.ts +344 -344
  107. package/src/memory/formation/types.ts +315 -315
  108. package/src/memory/freshness.ts +122 -122
  109. package/src/memory/graph.ts +197 -197
  110. package/src/memory/refs.ts +94 -94
  111. package/src/memory/retention.ts +433 -433
  112. package/src/memory/secret-filter.ts +79 -79
  113. package/src/memory/session.ts +523 -523
  114. package/src/multimodal/image-loader.ts +143 -143
  115. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  116. package/src/orchestrate/adapters/claude.ts +111 -111
  117. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  118. package/src/orchestrate/adapters/codex.ts +41 -41
  119. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  120. package/src/orchestrate/adapters/gemini.ts +42 -42
  121. package/src/orchestrate/adapters/index.ts +73 -73
  122. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  123. package/src/orchestrate/adapters/opencode.ts +47 -47
  124. package/src/orchestrate/adapters/spawn-helper.ts +286 -286
  125. package/src/orchestrate/adapters/types.ts +77 -77
  126. package/src/orchestrate/capability-router.ts +284 -284
  127. package/src/orchestrate/context-compact.ts +188 -188
  128. package/src/orchestrate/cost-tracker.ts +219 -219
  129. package/src/orchestrate/error-recovery.ts +191 -191
  130. package/src/orchestrate/evidence.ts +140 -140
  131. package/src/orchestrate/ledger.ts +110 -110
  132. package/src/orchestrate/memorix-bridge.ts +380 -380
  133. package/src/orchestrate/output-budget.ts +80 -80
  134. package/src/orchestrate/permission.ts +152 -152
  135. package/src/orchestrate/pipeline-trace.ts +131 -131
  136. package/src/orchestrate/prompt-builder.ts +155 -155
  137. package/src/orchestrate/ring-buffer.ts +37 -37
  138. package/src/orchestrate/task-graph.ts +389 -389
  139. package/src/orchestrate/verify-gate.ts +219 -219
  140. package/src/orchestrate/worktree.ts +232 -232
  141. package/src/project/aliases.ts +374 -374
  142. package/src/project/detector.ts +268 -268
  143. package/src/rules/adapters/claude-code.ts +99 -99
  144. package/src/rules/adapters/codex.ts +97 -97
  145. package/src/rules/adapters/copilot.ts +124 -124
  146. package/src/rules/adapters/cursor.ts +114 -114
  147. package/src/rules/adapters/kiro.ts +126 -126
  148. package/src/rules/adapters/trae.ts +56 -56
  149. package/src/rules/adapters/windsurf.ts +83 -83
  150. package/src/rules/syncer.ts +235 -235
  151. package/src/sdk.ts +327 -327
  152. package/src/search/intent-detector.ts +289 -289
  153. package/src/search/query-expansion.ts +52 -52
  154. package/src/server/formation-timeout.ts +27 -27
  155. package/src/server.ts +3 -0
  156. package/src/skills/mini-skills.ts +386 -386
  157. package/src/store/chat-store.ts +119 -119
  158. package/src/store/file-lock.ts +100 -100
  159. package/src/store/graph-store.ts +249 -249
  160. package/src/store/mini-skill-store.ts +349 -349
  161. package/src/store/obs-store.ts +255 -255
  162. package/src/store/orama-store.ts +15 -8
  163. package/src/store/persistence-json.ts +212 -212
  164. package/src/store/persistence.ts +291 -291
  165. package/src/store/project-affinity.ts +195 -195
  166. package/src/store/session-store.ts +259 -259
  167. package/src/store/sqlite-store.ts +339 -339
  168. package/src/team/event-bus.ts +76 -76
  169. package/src/team/file-locks.ts +173 -173
  170. package/src/team/handoff.ts +167 -167
  171. package/src/team/messages.ts +203 -203
  172. package/src/team/poll.ts +132 -132
  173. package/src/team/tasks.ts +211 -211
  174. package/src/wiki/generator.ts +237 -237
  175. package/src/wiki/knowledge-graph.ts +334 -334
  176. package/src/wiki/types.ts +85 -85
  177. package/src/workspace/mcp-adapters/codex.ts +191 -191
  178. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  179. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  180. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  181. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  182. package/src/workspace/mcp-adapters/trae.ts +134 -134
  183. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  184. package/src/workspace/sanitizer.ts +60 -60
  185. package/src/workspace/workflow-sync.ts +131 -131
package/dist/index.js CHANGED
@@ -1787,6 +1787,7 @@ function loadYamlConfig(projectRoot) {
1787
1787
  agent: { ...userConfig.agent, ...projectConfig.agent },
1788
1788
  embedding: { ...userConfig.embedding, ...projectConfig.embedding },
1789
1789
  git: { ...userConfig.git, ...projectConfig.git },
1790
+ codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
1790
1791
  behavior: { ...userConfig.behavior, ...projectConfig.behavior },
1791
1792
  server: { ...userConfig.server, ...projectConfig.server },
1792
1793
  team: { ...userConfig.team, ...projectConfig.team }
@@ -2069,6 +2070,7 @@ function mergeTomlConfig(base, override) {
2069
2070
  embedding: { ...base.embedding, ...override.embedding },
2070
2071
  hooks: { ...base.hooks, ...override.hooks },
2071
2072
  git: { ...base.git, ...override.git },
2073
+ codegraph: { ...base.codegraph, ...override.codegraph },
2072
2074
  server: { ...base.server, ...override.server }
2073
2075
  };
2074
2076
  }
@@ -2210,6 +2212,15 @@ var init_dotenv_loader = __esm({
2210
2212
  });
2211
2213
 
2212
2214
  // src/config/resolved-config.ts
2215
+ var resolved_config_exports = {};
2216
+ __export(resolved_config_exports, {
2217
+ getResolvedAgentLane: () => getResolvedAgentLane,
2218
+ getResolvedConfig: () => getResolvedConfig,
2219
+ getResolvedConfigForCwd: () => getResolvedConfigForCwd,
2220
+ getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
2221
+ getResolvedMemoryLane: () => getResolvedMemoryLane,
2222
+ resetResolvedConfigCache: () => resetResolvedConfigCache
2223
+ });
2213
2224
  import { homedir as homedir5 } from "os";
2214
2225
  import { existsSync as existsSync6 } from "fs";
2215
2226
  function getResolvedConfig(options = {}) {
@@ -2287,6 +2298,9 @@ function getResolvedConfig(options = {}) {
2287
2298
  excludePatterns: firstArray(toml.git?.exclude_patterns, yaml2.git?.excludePatterns),
2288
2299
  noiseKeywords: firstArray(toml.git?.noise_keywords, yaml2.git?.noiseKeywords)
2289
2300
  },
2301
+ codegraph: {
2302
+ excludePatterns: firstArray(toml.codegraph?.exclude_patterns, yaml2.codegraph?.excludePatterns)
2303
+ },
2290
2304
  server: {
2291
2305
  transport: first(toml.server?.transport, yaml2.server?.transport),
2292
2306
  dashboard: firstBool(toml.server?.dashboard, yaml2.server?.dashboard),
@@ -2308,6 +2322,10 @@ function getResolvedConfig(options = {}) {
2308
2322
  };
2309
2323
  return resolved;
2310
2324
  }
2325
+ function getResolvedConfigForCwd(cwd = process.cwd()) {
2326
+ const project = detectProject(cwd);
2327
+ return getResolvedConfig({ projectRoot: project?.rootPath ?? null });
2328
+ }
2311
2329
  function getResolvedAgentLane(options = {}) {
2312
2330
  const resolved = getResolvedConfig(options);
2313
2331
  return {
@@ -2324,6 +2342,8 @@ function getResolvedMemoryLane(options = {}) {
2324
2342
  function getResolvedEmbeddingLane(options = {}) {
2325
2343
  return getResolvedConfig(options).embedding;
2326
2344
  }
2345
+ function resetResolvedConfigCache() {
2346
+ }
2327
2347
  function first(...values) {
2328
2348
  return values.find((value) => value !== void 0 && value !== null && value !== "");
2329
2349
  }
@@ -4818,7 +4838,7 @@ __export(orama_store_exports, {
4818
4838
  resetDb: () => resetDb,
4819
4839
  searchObservations: () => searchObservations
4820
4840
  });
4821
- import { create, insert as insert2, search, remove as remove2, update, count } from "@orama/orama";
4841
+ import { create, insert as insert2, search, remove as remove2, update, count, getByID } from "@orama/orama";
4822
4842
  function getLastSearchMode(projectId) {
4823
4843
  return lastSearchModeByProject.get(projectId ?? SEARCH_MODE_DEFAULT_KEY) ?? "fulltext";
4824
4844
  }
@@ -4829,8 +4849,12 @@ function makeEntryKey(projectId, observationId) {
4829
4849
  return `${projectId ?? ""}::${observationId}`;
4830
4850
  }
4831
4851
  function rememberObservationDoc(doc) {
4832
- if (!doc.projectId || typeof doc.observationId !== "number") return;
4833
- docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), doc);
4852
+ const publicDoc = { ...doc };
4853
+ delete publicDoc.embedding;
4854
+ if (doc.projectId && typeof doc.observationId === "number") {
4855
+ docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), publicDoc);
4856
+ }
4857
+ return publicDoc;
4834
4858
  }
4835
4859
  function isCommandLikeQuery(query) {
4836
4860
  return COMMAND_LIKE_QUERY2.test(query);
@@ -4932,14 +4956,14 @@ async function batchGenerateEmbeddings(texts) {
4932
4956
  }
4933
4957
  async function hydrateIndex(observations2) {
4934
4958
  const database = await getDb();
4935
- const currentCount = await count(database);
4936
- if (currentCount > 0) return 0;
4937
4959
  let inserted = 0;
4938
4960
  for (const obs of observations2) {
4939
4961
  if (!obs || !obs.id || !obs.projectId) continue;
4940
4962
  try {
4963
+ const id = makeOramaObservationId(obs.projectId, obs.id);
4964
+ if (getByID(database, id)) continue;
4941
4965
  const doc = {
4942
- id: makeOramaObservationId(obs.projectId, obs.id),
4966
+ id,
4943
4967
  observationId: obs.id,
4944
4968
  entityName: obs.entityName || "",
4945
4969
  type: obs.type || "discovery",
@@ -5033,6 +5057,7 @@ async function searchObservations(options) {
5033
5057
  let searchParams = {
5034
5058
  term: originalQuery,
5035
5059
  limit: requestLimit,
5060
+ includeVectors: true,
5036
5061
  ...Object.keys(filters).length > 0 ? { where: filters } : {},
5037
5062
  // Search specific fields (not tokens, accessCount, etc.)
5038
5063
  properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
@@ -5104,6 +5129,7 @@ async function searchObservations(options) {
5104
5129
  const vectorOnlyParams = {
5105
5130
  term: "",
5106
5131
  limit: requestLimit,
5132
+ includeVectors: true,
5107
5133
  ...Object.keys(filters).length > 0 ? { where: filters } : {},
5108
5134
  mode: "vector",
5109
5135
  vector: {
@@ -5402,6 +5428,7 @@ async function getObservationsByIds(ids, projectId) {
5402
5428
  }
5403
5429
  const searchResult = await search(database, {
5404
5430
  term: "",
5431
+ includeVectors: true,
5405
5432
  where: {
5406
5433
  observationId: { eq: id },
5407
5434
  ...projectId ? { projectId } : {}
@@ -5409,7 +5436,7 @@ async function getObservationsByIds(ids, projectId) {
5409
5436
  limit: 1
5410
5437
  });
5411
5438
  if (searchResult.hits.length > 0) {
5412
- results.push(searchResult.hits[0].document);
5439
+ results.push(rememberObservationDoc(searchResult.hits[0].document));
5413
5440
  }
5414
5441
  }
5415
5442
  return results;
@@ -9296,6 +9323,58 @@ var init_current_facts = __esm({
9296
9323
  }
9297
9324
  });
9298
9325
 
9326
+ // src/codegraph/exclude.ts
9327
+ function normalizeCodeGraphExcludePatterns(exclude) {
9328
+ return [.../* @__PURE__ */ new Set([
9329
+ ...DEFAULT_CODEGRAPH_EXCLUDES,
9330
+ ...(exclude ?? []).map((pattern) => pattern.trim()).filter(Boolean)
9331
+ ])];
9332
+ }
9333
+ function isCodeGraphExcludedPath(path20, exclude) {
9334
+ const normalized = normalizeCodePath2(path20);
9335
+ return normalizeCodeGraphExcludePatterns(exclude).some((pattern) => matchesPattern(normalized, normalizeCodePath2(pattern)));
9336
+ }
9337
+ function normalizeCodePath2(path20) {
9338
+ return path20.replace(/\\/g, "/").replace(/^\.\/+/, "");
9339
+ }
9340
+ function matchesPattern(path20, pattern) {
9341
+ if (pattern.endsWith("/**")) {
9342
+ const base = pattern.slice(0, -3);
9343
+ if (base.startsWith("**/")) {
9344
+ const suffix = base.slice(3);
9345
+ return path20 === suffix || path20.endsWith(`/${suffix}`) || path20.includes(`/${suffix}/`);
9346
+ }
9347
+ if (!base.includes("/")) {
9348
+ return path20 === base || path20.startsWith(`${base}/`) || path20.includes(`/${base}/`);
9349
+ }
9350
+ return path20 === base || path20.startsWith(`${base}/`);
9351
+ }
9352
+ if (pattern.startsWith("**/")) {
9353
+ const suffix = pattern.slice(3);
9354
+ return path20 === suffix || path20.endsWith(`/${suffix}`);
9355
+ }
9356
+ return path20 === pattern || path20.startsWith(`${pattern}/`);
9357
+ }
9358
+ var DEFAULT_CODEGRAPH_EXCLUDES;
9359
+ var init_exclude = __esm({
9360
+ "src/codegraph/exclude.ts"() {
9361
+ "use strict";
9362
+ init_esm_shims();
9363
+ DEFAULT_CODEGRAPH_EXCLUDES = [
9364
+ "node_modules/**",
9365
+ "dist/**",
9366
+ "build/**",
9367
+ "coverage/**",
9368
+ ".next/**",
9369
+ ".turbo/**",
9370
+ ".git/**",
9371
+ ".tmp/**",
9372
+ ".worktrees/**",
9373
+ ".claude/worktrees/**"
9374
+ ];
9375
+ }
9376
+ });
9377
+
9299
9378
  // src/codegraph/lite-provider.ts
9300
9379
  import { createHash as createHash5 } from "crypto";
9301
9380
  import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
@@ -9311,18 +9390,6 @@ function languageForPath(path20) {
9311
9390
  const ext = extension(path20);
9312
9391
  return LANGUAGE_BY_EXTENSION.get(ext) ?? "unknown";
9313
9392
  }
9314
- function isExcluded(path20, exclude) {
9315
- const normalized = normalizeCodePath(path20);
9316
- return exclude.some((pattern) => {
9317
- const p = normalizeCodePath(pattern);
9318
- if (p.endsWith("/**")) {
9319
- const base = p.slice(0, -3);
9320
- return normalized === base || normalized.startsWith(`${base}/`);
9321
- }
9322
- if (p.startsWith("**/")) return normalized.endsWith(p.slice(3));
9323
- return normalized === p || normalized.startsWith(`${p}/`);
9324
- });
9325
- }
9326
9393
  function walk(root, exclude, maxFiles) {
9327
9394
  const out = [];
9328
9395
  const visit = (dir) => {
@@ -9336,9 +9403,10 @@ function walk(root, exclude, maxFiles) {
9336
9403
  for (const entry of entries) {
9337
9404
  const abs = join20(dir, entry.name);
9338
9405
  const rel = normalizeCodePath(relative(root, abs));
9339
- if (isExcluded(rel, exclude)) continue;
9406
+ if (isCodeGraphExcludedPath(rel, exclude)) continue;
9340
9407
  if (entry.isDirectory()) {
9341
- if (entry.name === ".git" || entry.name === "node_modules") continue;
9408
+ if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
9409
+ if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
9342
9410
  visit(abs);
9343
9411
  if (out.length >= maxFiles) return;
9344
9412
  continue;
@@ -9423,15 +9491,7 @@ function extractImportEdges(projectId, file, text, indexedAt) {
9423
9491
  return edges;
9424
9492
  }
9425
9493
  async function indexProjectLite(options) {
9426
- const exclude = options.exclude ?? [
9427
- "node_modules/**",
9428
- "dist/**",
9429
- "build/**",
9430
- "coverage/**",
9431
- ".next/**",
9432
- ".turbo/**",
9433
- ".git/**"
9434
- ];
9494
+ const exclude = normalizeCodeGraphExcludePatterns(options.exclude);
9435
9495
  const maxFiles = options.maxFiles ?? 5e3;
9436
9496
  const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
9437
9497
  const paths = walk(options.projectRoot, exclude, maxFiles);
@@ -9470,6 +9530,7 @@ var init_lite_provider = __esm({
9470
9530
  "use strict";
9471
9531
  init_esm_shims();
9472
9532
  init_ids();
9533
+ init_exclude();
9473
9534
  LANGUAGE_BY_EXTENSION = /* @__PURE__ */ new Map([
9474
9535
  [".ts", "typescript"],
9475
9536
  [".tsx", "typescript"],
@@ -9639,23 +9700,17 @@ function countLanguages(files) {
9639
9700
  }
9640
9701
  return [...counts.entries()].map(([language, files2]) => ({ language, files: files2 })).sort((a, b) => a.language.localeCompare(b.language));
9641
9702
  }
9642
- function normalizePath2(path20) {
9643
- return path20.replace(/\\/g, "/");
9644
- }
9645
- function isGeneratedPath(path20) {
9646
- return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(normalizePath2(path20));
9647
- }
9648
9703
  function suggestedReadRank(path20) {
9649
- const normalized = normalizePath2(path20);
9704
+ const normalized = path20.replace(/\\/g, "/");
9650
9705
  if (normalized.startsWith("src/")) return 0;
9651
9706
  if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 0;
9652
9707
  if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
9653
9708
  return 3;
9654
9709
  }
9655
- function compactSuggestedReads(paths, limit = 8) {
9656
- return uniq(paths).filter((path20) => !isGeneratedPath(path20)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
9710
+ function compactSuggestedReads(paths, limit = 8, exclude) {
9711
+ return uniq(paths).filter((path20) => !isCodeGraphExcludedPath(path20, exclude)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
9657
9712
  }
9658
- function collectGraph(store, projectId, observations2) {
9713
+ function collectGraph(store, projectId, observations2, exclude) {
9659
9714
  const files = store.listFiles(projectId);
9660
9715
  const symbols = files.flatMap((file) => store.listSymbolsForFile(file.id));
9661
9716
  const filesById = new Map(files.map((file) => [file.id, file]));
@@ -9677,7 +9732,9 @@ function collectGraph(store, projectId, observations2) {
9677
9732
  freshness[result.status] += 1;
9678
9733
  const observation = observationsById.get(ref.observationId);
9679
9734
  if (!observation) continue;
9680
- if (result.status === "current" && file) suggestedReads.push(file.path);
9735
+ const excluded = file ? isCodeGraphExcludedPath(file.path, exclude) : false;
9736
+ if (result.status === "current" && file && !excluded) suggestedReads.push(file.path);
9737
+ if (excluded) continue;
9681
9738
  sources.push({
9682
9739
  observationId: observation.id,
9683
9740
  title: observation.title,
@@ -9694,12 +9751,12 @@ function collectGraph(store, projectId, observations2) {
9694
9751
  refs,
9695
9752
  freshness,
9696
9753
  sources,
9697
- suggestedReads: compactSuggestedReads(suggestedReads)
9754
+ suggestedReads: compactSuggestedReads(suggestedReads, 8, exclude)
9698
9755
  };
9699
9756
  }
9700
9757
  function buildProjectContextOverview(input) {
9701
9758
  const active = activeObservations(input.observations, input.project.id);
9702
- const graph = collectGraph(input.store, input.project.id, active);
9759
+ const graph = collectGraph(input.store, input.project.id, active, input.exclude);
9703
9760
  const status = input.store.status(input.project.id);
9704
9761
  return {
9705
9762
  project: input.project,
@@ -9723,7 +9780,7 @@ function buildProjectContextOverview(input) {
9723
9780
  function buildProjectContextExplain(input) {
9724
9781
  const overview = buildProjectContextOverview(input);
9725
9782
  const active = activeObservations(input.observations, input.project.id);
9726
- const graph = collectGraph(input.store, input.project.id, active);
9783
+ const graph = collectGraph(input.store, input.project.id, active, input.exclude);
9727
9784
  return {
9728
9785
  project: input.project,
9729
9786
  sources: graph.sources.sort((a, b) => a.observationId - b.observationId || (a.path ?? "").localeCompare(b.path ?? "")),
@@ -9735,11 +9792,12 @@ var init_project_context = __esm({
9735
9792
  "use strict";
9736
9793
  init_esm_shims();
9737
9794
  init_freshness2();
9795
+ init_exclude();
9738
9796
  }
9739
9797
  });
9740
9798
 
9741
9799
  // src/codegraph/task-lens.ts
9742
- function normalizePath3(path20) {
9800
+ function normalizePath2(path20) {
9743
9801
  return path20.replace(/\\/g, "/");
9744
9802
  }
9745
9803
  function tokenize(text) {
@@ -9769,7 +9827,7 @@ function resolveTaskLens(task) {
9769
9827
  return best.score > 0 ? LENSES[best.id] : LENSES.general;
9770
9828
  }
9771
9829
  function pathKindScore(path20, lens) {
9772
- const normalized = normalizePath3(path20).toLowerCase();
9830
+ const normalized = normalizePath2(path20).toLowerCase();
9773
9831
  const name = normalized.split("/").pop() ?? normalized;
9774
9832
  const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
9775
9833
  const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
@@ -9818,7 +9876,7 @@ function sourceTaskMatchScore(source, task) {
9818
9876
  return 0;
9819
9877
  }
9820
9878
  function fallbackPathRank(path20) {
9821
- const normalized = normalizePath3(path20);
9879
+ const normalized = normalizePath2(path20);
9822
9880
  if (normalized.startsWith("src/")) return 0;
9823
9881
  if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
9824
9882
  if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
@@ -9827,7 +9885,7 @@ function fallbackPathRank(path20) {
9827
9885
  }
9828
9886
  function rankLensPaths(paths, lens, task) {
9829
9887
  const tokens = tokenize(task ?? "");
9830
- return [...new Set(paths.map(normalizePath3))].map((path20, index) => ({
9888
+ return [...new Set(paths.map(normalizePath2))].map((path20, index) => ({
9831
9889
  path: path20,
9832
9890
  index,
9833
9891
  score: pathKindScore(path20, lens) + tokenScore(path20, tokens),
@@ -10081,6 +10139,7 @@ async function buildAutoProjectContext(input) {
10081
10139
  const now = input.now ?? /* @__PURE__ */ new Date();
10082
10140
  const task = input.task?.trim();
10083
10141
  const lens = resolveTaskLens(task);
10142
+ const exclude = input.exclude ?? getResolvedConfig({ projectRoot: input.project.rootPath }).codegraph.excludePatterns;
10084
10143
  const store = new CodeGraphStore();
10085
10144
  await store.init(input.dataDir);
10086
10145
  const initialStatus = store.status(input.project.id);
@@ -10098,7 +10157,8 @@ async function buildAutoProjectContext(input) {
10098
10157
  try {
10099
10158
  const indexed = await indexProjectLite({
10100
10159
  projectId: input.project.id,
10101
- projectRoot: input.project.rootPath
10160
+ projectRoot: input.project.rootPath,
10161
+ exclude
10102
10162
  });
10103
10163
  store.replaceProjectIndex(input.project.id, indexed);
10104
10164
  const backfill = await backfillMissingObservationCodeRefs(
@@ -10118,12 +10178,14 @@ async function buildAutoProjectContext(input) {
10118
10178
  const overview = buildProjectContextOverview({
10119
10179
  project: input.project,
10120
10180
  store,
10121
- observations: input.observations
10181
+ observations: input.observations,
10182
+ exclude
10122
10183
  });
10123
10184
  const explain = buildProjectContextExplain({
10124
10185
  project: input.project,
10125
10186
  store,
10126
- observations: input.observations
10187
+ observations: input.observations,
10188
+ exclude
10127
10189
  });
10128
10190
  return {
10129
10191
  project: input.project,
@@ -10333,6 +10395,7 @@ var init_auto_context = __esm({
10333
10395
  "src/codegraph/auto-context.ts"() {
10334
10396
  "use strict";
10335
10397
  init_esm_shims();
10398
+ init_resolved_config();
10336
10399
  init_binder();
10337
10400
  init_current_facts();
10338
10401
  init_lite_provider();
@@ -10360,9 +10423,6 @@ function tokenize2(text) {
10360
10423
  function timestampOf(observation) {
10361
10424
  return Date.parse(observation.updatedAt ?? observation.createdAt ?? "") || 0;
10362
10425
  }
10363
- function isGeneratedPath2(path20) {
10364
- return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(path20.replace(/\\/g, "/"));
10365
- }
10366
10426
  function relevanceScore(observation, taskTokens) {
10367
10427
  if (taskTokens.length === 0) return 0;
10368
10428
  const title = observation.title.toLowerCase();
@@ -10413,7 +10473,8 @@ function assembleContextPackForTask(input) {
10413
10473
  refs,
10414
10474
  files,
10415
10475
  symbols,
10416
- suggestedVerification: input.suggestedVerification
10476
+ suggestedVerification: input.suggestedVerification,
10477
+ exclude: input.exclude
10417
10478
  });
10418
10479
  }
10419
10480
  function assembleContextPack(input) {
@@ -10432,6 +10493,7 @@ function assembleContextPack(input) {
10432
10493
  observationIdsWithRefs.add(ref.observationId);
10433
10494
  const file = ref.fileId ? files.get(ref.fileId) : void 0;
10434
10495
  const symbol = ref.symbolId ? symbols.get(ref.symbolId) : void 0;
10496
+ if (file && isCodeGraphExcludedPath(file.path, input.exclude)) continue;
10435
10497
  const freshness = evaluateCodeRefFreshness(ref, file, symbol);
10436
10498
  if (freshness.status === "current") {
10437
10499
  const memoryKey = `${observation.id}:${freshness.status}`;
@@ -10497,8 +10559,8 @@ function buildContextPackPrompt(pack) {
10497
10559
  const reliableMemories = pack.memories.filter((memory) => memory.status === "current");
10498
10560
  const unboundMemories = pack.memories.filter((memory) => memory.status === "unbound");
10499
10561
  const lines = ["## Task", pack.task, "", "## Reliable Memories"];
10500
- const visibleCodeFacts = pack.codeFacts.filter((fact) => !isGeneratedPath2(fact.path)).slice(0, 5);
10501
- const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isGeneratedPath2(path20)).slice(0, 5);
10562
+ const visibleCodeFacts = pack.codeFacts.filter((fact) => !isCodeGraphExcludedPath(fact.path)).slice(0, 5);
10563
+ const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isCodeGraphExcludedPath(path20)).slice(0, 5);
10502
10564
  if (reliableMemories.length === 0) lines.push("- none");
10503
10565
  for (const memory of reliableMemories) {
10504
10566
  lines.push(`- #${memory.id} ${memory.status}: [${memory.type}] ${memory.title} (${memory.reason})`);
@@ -10533,6 +10595,7 @@ var init_context_pack = __esm({
10533
10595
  "use strict";
10534
10596
  init_esm_shims();
10535
10597
  init_freshness2();
10598
+ init_exclude();
10536
10599
  }
10537
10600
  });
10538
10601
 
@@ -14551,7 +14614,7 @@ var init_official_skills = __esm({
14551
14614
  "",
14552
14615
  "## Search Rules",
14553
14616
  "",
14554
- "- Use `memorix_project_context` before broad continuation work, unfamiliar code changes, ad-hoc file reads, or dev-log reads. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
14617
+ "- Default first step for non-trivial coding work: call `memorix_project_context` before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Pass the user's actual task so Memorix can choose a bugfix, feature, release, onboarding, refactor, docs, test, or general brief. Start by reading its suggested files.",
14555
14618
  "- In Claude Code headless/print-mode, an initial MCP `pending` status is not a failure by itself. Prefer MCP first: use the client's tool discovery/dynamic loading to find `memorix_project_context` when it is not in the first visible tool list.",
14556
14619
  '- Run `memorix context --task "<task>"` from the shell only after MCP is unavailable, disabled, or not discoverable, and pass the user\'s real task text. Do not skip memory, wait indefinitely on `pending`, or hand-write tool-call syntax.',
14557
14620
  "- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer.",
@@ -14862,6 +14925,7 @@ var init_audit = __esm({
14862
14925
  var installers_exports = {};
14863
14926
  __export(installers_exports, {
14864
14927
  detectInstalledAgents: () => detectInstalledAgents,
14928
+ getAgentRulesPath: () => getAgentRulesPath,
14865
14929
  getGlobalConfigPath: () => getGlobalConfigPath,
14866
14930
  getHookStatus: () => getHookStatus,
14867
14931
  getProjectConfigPath: () => getProjectConfigPath,
@@ -15728,7 +15792,7 @@ function getAgentRulesContent(agent, scope = "project") {
15728
15792
  let frontmatter = "";
15729
15793
  const contextNoun = scope === "global" ? "workspace" : "project";
15730
15794
  const title = scope === "global" ? "# Memorix \u2014 Memory Tools for Active Workspaces" : "# Memorix \u2014 Project Memory Tools";
15731
- const intro = scope === "global" ? "Use Memorix when the active workspace has Memorix tools available and prior context would materially help. Do not assume every workspace is configured for Memorix." : "This repository is configured to use Memorix for persistent cross-session memory. Memory tools are available when you need context from prior sessions or when you learn something worth saving.";
15795
+ const intro = scope === "global" ? "Use Memorix when the active workspace has Memorix tools available and prior context would materially help. For non-trivial coding work, Memory Autopilot is the default entry point before local progress notes or broad file exploration. Do not assume every workspace is configured for Memorix." : "This repository is configured to use Memorix for persistent cross-session memory. For non-trivial coding work, Memory Autopilot is the default entry point before local progress notes or broad file exploration.";
15732
15796
  if (agent === "windsurf") {
15733
15797
  frontmatter = "---\ntrigger: always_on\n---\n\n";
15734
15798
  } else if (agent === "cursor") {
@@ -15746,7 +15810,7 @@ alwaysApply: true
15746
15810
  "",
15747
15811
  "## Start with Memory Autopilot",
15748
15812
  "",
15749
- `For starting or continuing code work, use \`memorix_project_context\` with the user's actual task before ad-hoc file reads, dev-log reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
15813
+ `Default first step for non-trivial coding work: call \`memorix_project_context\` with the user's actual task before progress files, dev-log reads, ad-hoc file reads, or git archaeology. Memorix will choose a task-lensed brief (bugfix, feature, release, onboarding, refactor, docs, test, or general). Treat its "Start here" files as the first ${contextNoun} files to inspect.`,
15750
15814
  "",
15751
15815
  'If the MCP tool is not visible yet but the client supports tool discovery or dynamic loading, search/select `memorix_project_context` first. Run `memorix context --task "<task>"` only after MCP is unavailable, disabled, or not discoverable, and pass the user\'s real task text. Do not skip memory, wait indefinitely on MCP startup, or hand-write tool-call syntax.',
15752
15816
  "",
@@ -20002,7 +20066,7 @@ The path should point to a directory containing a .git folder.`
20002
20066
  };
20003
20067
  const server = existingServer ?? new McpServer({
20004
20068
  name: "memorix",
20005
- version: true ? "1.1.7" : "1.0.1"
20069
+ version: true ? "1.1.9" : "1.0.1"
20006
20070
  });
20007
20071
  const originalRegisterTool = server.registerTool.bind(server);
20008
20072
  server.registerTool = ((name, ...args) => {
@@ -20704,15 +20768,18 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
20704
20768
  return withFreshIndex(async () => {
20705
20769
  const { CodeGraphStore: CodeGraphStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
20706
20770
  const { assembleContextPackForTask: assembleContextPackForTask2, buildContextPackPrompt: buildContextPackPrompt2 } = await Promise.resolve().then(() => (init_context_pack(), context_pack_exports));
20771
+ const { getResolvedConfig: getResolvedConfig2 } = await Promise.resolve().then(() => (init_resolved_config(), resolved_config_exports));
20707
20772
  const store = new CodeGraphStore2();
20708
20773
  await store.init(projectDir2);
20774
+ const exclude = getResolvedConfig2({ projectRoot: project.rootPath }).codegraph.excludePatterns;
20709
20775
  const observations2 = getAllObservations().filter((obs) => obs.projectId === project.id && (obs.status ?? "active") === "active").reverse();
20710
20776
  const pack = assembleContextPackForTask2({
20711
20777
  store,
20712
20778
  projectId: project.id,
20713
20779
  task,
20714
20780
  observations: observations2,
20715
- limit: typeof limit === "number" ? limit : 20
20781
+ limit: typeof limit === "number" ? limit : 20,
20782
+ exclude
20716
20783
  });
20717
20784
  const text = buildContextPackPrompt2(pack);
20718
20785
  return {