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
@@ -2,6 +2,28 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [1.1.9] - 2026-07-12
6
+
7
+ ### Added
8
+ - **Configurable CodeGraph excludes** -- Added `[codegraph].exclude_patterns` / YAML `codegraph.excludePatterns` support so CodeGraph, Project Context suggested reads, context packs, diagnostics, and related CLI flows can skip project-specific generated or vendor paths while keeping the built-in defaults.
9
+
10
+ ### Fixed
11
+ - **Config inspection aliases** -- `memorix config get` now accepts TOML-style snake_case dotted keys such as `codegraph.exclude_patterns` when reading resolved camelCase config values.
12
+ - **Orama search index consistency** -- Search access tracking now preserves internally stored vector-backed documents, public/detail cache results continue to strip embeddings, and hydration reconciles persisted observations by exact composite ID instead of skipping observation hydration when a shared index already contains mini-skills.
13
+
14
+ ## [1.1.8] - 2026-07-08
15
+
16
+ ### Added
17
+ - **Agent integration doctor and repair** -- Added `memorix doctor agents` and `memorix repair agents` to inspect and repair Memorix-owned agent integration files. The doctor flags stale MCP command paths, missing Claude `alwaysLoad`, missing `memorix` MCP entries, and outdated Memory Autopilot guidance without printing environment secrets.
18
+
19
+ ### Changed
20
+ - **Memory Autopilot adoption** -- Setup-generated agent guidance now makes `memorix_project_context` the default first step for non-trivial coding work before progress files, dev logs, broad file reads, or git archaeology.
21
+
22
+ ### Fixed
23
+ - **Claude Code local MCP repair** -- `memorix doctor agents` and `memorix repair agents` now inspect and repair Claude Code 2.x project-private local MCP entries in `~/.claude.json`, replacing stale worktree commands with `memorix serve` and `alwaysLoad: true`.
24
+ - **Cleaner CodeGraph Memory briefs** -- CodeGraph Lite and Memory Autopilot now ignore `.tmp`, nested `.worktrees`, and `.claude/worktrees` directories, so suggested reads point at the real project instead of local caches or agent scratch worktrees.
25
+ - **All-scope doctor noise** -- Agent doctor now treats one healthy local, project, or global scope as sufficient in all-scope mode, while still flagging genuinely stale or repairable configs.
26
+
5
27
  ## [1.1.7] - 2026-07-07
6
28
 
7
29
  ### Added
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memorix/memcode",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "Memorix-native coding agent CLI with terminal chat, project memory, hooks, and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -34,9 +34,9 @@
34
34
  "prepublishOnly": "npm run clean && npm run build"
35
35
  },
36
36
  "dependencies": {
37
- "@memorix/agent-core": "1.1.7",
38
- "@memorix/ai": "1.1.7",
39
- "@memorix/tui": "1.1.7",
37
+ "@memorix/agent-core": "1.1.9",
38
+ "@memorix/ai": "1.1.9",
39
+ "@memorix/tui": "1.1.9",
40
40
  "@opentui/core": "^0.3.4",
41
41
  "@opentui/react": "^0.3.4",
42
42
  "@silvia-odwyer/photon-node": "0.3.4",
package/dist/sdk.js CHANGED
@@ -1791,6 +1791,7 @@ function loadYamlConfig(projectRoot) {
1791
1791
  agent: { ...userConfig.agent, ...projectConfig.agent },
1792
1792
  embedding: { ...userConfig.embedding, ...projectConfig.embedding },
1793
1793
  git: { ...userConfig.git, ...projectConfig.git },
1794
+ codegraph: { ...userConfig.codegraph, ...projectConfig.codegraph },
1794
1795
  behavior: { ...userConfig.behavior, ...projectConfig.behavior },
1795
1796
  server: { ...userConfig.server, ...projectConfig.server },
1796
1797
  team: { ...userConfig.team, ...projectConfig.team }
@@ -2073,6 +2074,7 @@ function mergeTomlConfig(base, override) {
2073
2074
  embedding: { ...base.embedding, ...override.embedding },
2074
2075
  hooks: { ...base.hooks, ...override.hooks },
2075
2076
  git: { ...base.git, ...override.git },
2077
+ codegraph: { ...base.codegraph, ...override.codegraph },
2076
2078
  server: { ...base.server, ...override.server }
2077
2079
  };
2078
2080
  }
@@ -2214,6 +2216,15 @@ var init_dotenv_loader = __esm({
2214
2216
  });
2215
2217
 
2216
2218
  // src/config/resolved-config.ts
2219
+ var resolved_config_exports = {};
2220
+ __export(resolved_config_exports, {
2221
+ getResolvedAgentLane: () => getResolvedAgentLane,
2222
+ getResolvedConfig: () => getResolvedConfig,
2223
+ getResolvedConfigForCwd: () => getResolvedConfigForCwd,
2224
+ getResolvedEmbeddingLane: () => getResolvedEmbeddingLane,
2225
+ getResolvedMemoryLane: () => getResolvedMemoryLane,
2226
+ resetResolvedConfigCache: () => resetResolvedConfigCache
2227
+ });
2217
2228
  import { homedir as homedir5 } from "os";
2218
2229
  import { existsSync as existsSync6 } from "fs";
2219
2230
  function getResolvedConfig(options = {}) {
@@ -2291,6 +2302,9 @@ function getResolvedConfig(options = {}) {
2291
2302
  excludePatterns: firstArray(toml.git?.exclude_patterns, yaml2.git?.excludePatterns),
2292
2303
  noiseKeywords: firstArray(toml.git?.noise_keywords, yaml2.git?.noiseKeywords)
2293
2304
  },
2305
+ codegraph: {
2306
+ excludePatterns: firstArray(toml.codegraph?.exclude_patterns, yaml2.codegraph?.excludePatterns)
2307
+ },
2294
2308
  server: {
2295
2309
  transport: first(toml.server?.transport, yaml2.server?.transport),
2296
2310
  dashboard: firstBool(toml.server?.dashboard, yaml2.server?.dashboard),
@@ -2312,6 +2326,10 @@ function getResolvedConfig(options = {}) {
2312
2326
  };
2313
2327
  return resolved;
2314
2328
  }
2329
+ function getResolvedConfigForCwd(cwd = process.cwd()) {
2330
+ const project = detectProject(cwd);
2331
+ return getResolvedConfig({ projectRoot: project?.rootPath ?? null });
2332
+ }
2315
2333
  function getResolvedAgentLane(options = {}) {
2316
2334
  const resolved = getResolvedConfig(options);
2317
2335
  return {
@@ -2328,6 +2346,8 @@ function getResolvedMemoryLane(options = {}) {
2328
2346
  function getResolvedEmbeddingLane(options = {}) {
2329
2347
  return getResolvedConfig(options).embedding;
2330
2348
  }
2349
+ function resetResolvedConfigCache() {
2350
+ }
2331
2351
  function first(...values) {
2332
2352
  return values.find((value) => value !== void 0 && value !== null && value !== "");
2333
2353
  }
@@ -4822,7 +4842,7 @@ __export(orama_store_exports, {
4822
4842
  resetDb: () => resetDb,
4823
4843
  searchObservations: () => searchObservations
4824
4844
  });
4825
- import { create, insert as insert2, search, remove as remove2, update, count } from "@orama/orama";
4845
+ import { create, insert as insert2, search, remove as remove2, update, count, getByID } from "@orama/orama";
4826
4846
  function getLastSearchMode(projectId) {
4827
4847
  return lastSearchModeByProject.get(projectId ?? SEARCH_MODE_DEFAULT_KEY) ?? "fulltext";
4828
4848
  }
@@ -4833,8 +4853,12 @@ function makeEntryKey(projectId, observationId) {
4833
4853
  return `${projectId ?? ""}::${observationId}`;
4834
4854
  }
4835
4855
  function rememberObservationDoc(doc) {
4836
- if (!doc.projectId || typeof doc.observationId !== "number") return;
4837
- docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), doc);
4856
+ const publicDoc = { ...doc };
4857
+ delete publicDoc.embedding;
4858
+ if (doc.projectId && typeof doc.observationId === "number") {
4859
+ docByObservationKey.set(makeEntryKey(doc.projectId, doc.observationId), publicDoc);
4860
+ }
4861
+ return publicDoc;
4838
4862
  }
4839
4863
  function isCommandLikeQuery(query) {
4840
4864
  return COMMAND_LIKE_QUERY2.test(query);
@@ -4936,14 +4960,14 @@ async function batchGenerateEmbeddings(texts) {
4936
4960
  }
4937
4961
  async function hydrateIndex(observations2) {
4938
4962
  const database = await getDb();
4939
- const currentCount = await count(database);
4940
- if (currentCount > 0) return 0;
4941
4963
  let inserted = 0;
4942
4964
  for (const obs of observations2) {
4943
4965
  if (!obs || !obs.id || !obs.projectId) continue;
4944
4966
  try {
4967
+ const id = makeOramaObservationId(obs.projectId, obs.id);
4968
+ if (getByID(database, id)) continue;
4945
4969
  const doc = {
4946
- id: makeOramaObservationId(obs.projectId, obs.id),
4970
+ id,
4947
4971
  observationId: obs.id,
4948
4972
  entityName: obs.entityName || "",
4949
4973
  type: obs.type || "discovery",
@@ -5037,6 +5061,7 @@ async function searchObservations(options) {
5037
5061
  let searchParams = {
5038
5062
  term: originalQuery,
5039
5063
  limit: requestLimit,
5064
+ includeVectors: true,
5040
5065
  ...Object.keys(filters).length > 0 ? { where: filters } : {},
5041
5066
  // Search specific fields (not tokens, accessCount, etc.)
5042
5067
  properties: ["title", "entityName", "narrative", "facts", "concepts", "filesModified"],
@@ -5108,6 +5133,7 @@ async function searchObservations(options) {
5108
5133
  const vectorOnlyParams = {
5109
5134
  term: "",
5110
5135
  limit: requestLimit,
5136
+ includeVectors: true,
5111
5137
  ...Object.keys(filters).length > 0 ? { where: filters } : {},
5112
5138
  mode: "vector",
5113
5139
  vector: {
@@ -5406,6 +5432,7 @@ async function getObservationsByIds(ids, projectId) {
5406
5432
  }
5407
5433
  const searchResult = await search(database, {
5408
5434
  term: "",
5435
+ includeVectors: true,
5409
5436
  where: {
5410
5437
  observationId: { eq: id },
5411
5438
  ...projectId ? { projectId } : {}
@@ -5413,7 +5440,7 @@ async function getObservationsByIds(ids, projectId) {
5413
5440
  limit: 1
5414
5441
  });
5415
5442
  if (searchResult.hits.length > 0) {
5416
- results.push(searchResult.hits[0].document);
5443
+ results.push(rememberObservationDoc(searchResult.hits[0].document));
5417
5444
  }
5418
5445
  }
5419
5446
  return results;
@@ -9300,6 +9327,58 @@ var init_current_facts = __esm({
9300
9327
  }
9301
9328
  });
9302
9329
 
9330
+ // src/codegraph/exclude.ts
9331
+ function normalizeCodeGraphExcludePatterns(exclude) {
9332
+ return [.../* @__PURE__ */ new Set([
9333
+ ...DEFAULT_CODEGRAPH_EXCLUDES,
9334
+ ...(exclude ?? []).map((pattern) => pattern.trim()).filter(Boolean)
9335
+ ])];
9336
+ }
9337
+ function isCodeGraphExcludedPath(path20, exclude) {
9338
+ const normalized = normalizeCodePath2(path20);
9339
+ return normalizeCodeGraphExcludePatterns(exclude).some((pattern) => matchesPattern(normalized, normalizeCodePath2(pattern)));
9340
+ }
9341
+ function normalizeCodePath2(path20) {
9342
+ return path20.replace(/\\/g, "/").replace(/^\.\/+/, "");
9343
+ }
9344
+ function matchesPattern(path20, pattern) {
9345
+ if (pattern.endsWith("/**")) {
9346
+ const base = pattern.slice(0, -3);
9347
+ if (base.startsWith("**/")) {
9348
+ const suffix = base.slice(3);
9349
+ return path20 === suffix || path20.endsWith(`/${suffix}`) || path20.includes(`/${suffix}/`);
9350
+ }
9351
+ if (!base.includes("/")) {
9352
+ return path20 === base || path20.startsWith(`${base}/`) || path20.includes(`/${base}/`);
9353
+ }
9354
+ return path20 === base || path20.startsWith(`${base}/`);
9355
+ }
9356
+ if (pattern.startsWith("**/")) {
9357
+ const suffix = pattern.slice(3);
9358
+ return path20 === suffix || path20.endsWith(`/${suffix}`);
9359
+ }
9360
+ return path20 === pattern || path20.startsWith(`${pattern}/`);
9361
+ }
9362
+ var DEFAULT_CODEGRAPH_EXCLUDES;
9363
+ var init_exclude = __esm({
9364
+ "src/codegraph/exclude.ts"() {
9365
+ "use strict";
9366
+ init_esm_shims();
9367
+ DEFAULT_CODEGRAPH_EXCLUDES = [
9368
+ "node_modules/**",
9369
+ "dist/**",
9370
+ "build/**",
9371
+ "coverage/**",
9372
+ ".next/**",
9373
+ ".turbo/**",
9374
+ ".git/**",
9375
+ ".tmp/**",
9376
+ ".worktrees/**",
9377
+ ".claude/worktrees/**"
9378
+ ];
9379
+ }
9380
+ });
9381
+
9303
9382
  // src/codegraph/lite-provider.ts
9304
9383
  import { createHash as createHash5 } from "crypto";
9305
9384
  import { readdirSync as readdirSync3, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
@@ -9315,18 +9394,6 @@ function languageForPath(path20) {
9315
9394
  const ext = extension(path20);
9316
9395
  return LANGUAGE_BY_EXTENSION.get(ext) ?? "unknown";
9317
9396
  }
9318
- function isExcluded(path20, exclude) {
9319
- const normalized = normalizeCodePath(path20);
9320
- return exclude.some((pattern) => {
9321
- const p = normalizeCodePath(pattern);
9322
- if (p.endsWith("/**")) {
9323
- const base = p.slice(0, -3);
9324
- return normalized === base || normalized.startsWith(`${base}/`);
9325
- }
9326
- if (p.startsWith("**/")) return normalized.endsWith(p.slice(3));
9327
- return normalized === p || normalized.startsWith(`${p}/`);
9328
- });
9329
- }
9330
9397
  function walk(root, exclude, maxFiles) {
9331
9398
  const out = [];
9332
9399
  const visit = (dir) => {
@@ -9340,9 +9407,10 @@ function walk(root, exclude, maxFiles) {
9340
9407
  for (const entry of entries) {
9341
9408
  const abs = join20(dir, entry.name);
9342
9409
  const rel = normalizeCodePath(relative(root, abs));
9343
- if (isExcluded(rel, exclude)) continue;
9410
+ if (isCodeGraphExcludedPath(rel, exclude)) continue;
9344
9411
  if (entry.isDirectory()) {
9345
- if (entry.name === ".git" || entry.name === "node_modules") continue;
9412
+ if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
9413
+ if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
9346
9414
  visit(abs);
9347
9415
  if (out.length >= maxFiles) return;
9348
9416
  continue;
@@ -9427,15 +9495,7 @@ function extractImportEdges(projectId, file, text, indexedAt) {
9427
9495
  return edges;
9428
9496
  }
9429
9497
  async function indexProjectLite(options) {
9430
- const exclude = options.exclude ?? [
9431
- "node_modules/**",
9432
- "dist/**",
9433
- "build/**",
9434
- "coverage/**",
9435
- ".next/**",
9436
- ".turbo/**",
9437
- ".git/**"
9438
- ];
9498
+ const exclude = normalizeCodeGraphExcludePatterns(options.exclude);
9439
9499
  const maxFiles = options.maxFiles ?? 5e3;
9440
9500
  const indexedAt = (/* @__PURE__ */ new Date()).toISOString();
9441
9501
  const paths = walk(options.projectRoot, exclude, maxFiles);
@@ -9474,6 +9534,7 @@ var init_lite_provider = __esm({
9474
9534
  "use strict";
9475
9535
  init_esm_shims();
9476
9536
  init_ids();
9537
+ init_exclude();
9477
9538
  LANGUAGE_BY_EXTENSION = /* @__PURE__ */ new Map([
9478
9539
  [".ts", "typescript"],
9479
9540
  [".tsx", "typescript"],
@@ -9643,23 +9704,17 @@ function countLanguages(files) {
9643
9704
  }
9644
9705
  return [...counts.entries()].map(([language, files2]) => ({ language, files: files2 })).sort((a, b) => a.language.localeCompare(b.language));
9645
9706
  }
9646
- function normalizePath2(path20) {
9647
- return path20.replace(/\\/g, "/");
9648
- }
9649
- function isGeneratedPath(path20) {
9650
- return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(normalizePath2(path20));
9651
- }
9652
9707
  function suggestedReadRank(path20) {
9653
- const normalized = normalizePath2(path20);
9708
+ const normalized = path20.replace(/\\/g, "/");
9654
9709
  if (normalized.startsWith("src/")) return 0;
9655
9710
  if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 0;
9656
9711
  if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
9657
9712
  return 3;
9658
9713
  }
9659
- function compactSuggestedReads(paths, limit = 8) {
9660
- return uniq(paths).filter((path20) => !isGeneratedPath(path20)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
9714
+ function compactSuggestedReads(paths, limit = 8, exclude) {
9715
+ return uniq(paths).filter((path20) => !isCodeGraphExcludedPath(path20, exclude)).sort((a, b) => suggestedReadRank(a) - suggestedReadRank(b)).slice(0, limit);
9661
9716
  }
9662
- function collectGraph(store, projectId, observations2) {
9717
+ function collectGraph(store, projectId, observations2, exclude) {
9663
9718
  const files = store.listFiles(projectId);
9664
9719
  const symbols = files.flatMap((file) => store.listSymbolsForFile(file.id));
9665
9720
  const filesById = new Map(files.map((file) => [file.id, file]));
@@ -9681,7 +9736,9 @@ function collectGraph(store, projectId, observations2) {
9681
9736
  freshness[result.status] += 1;
9682
9737
  const observation = observationsById.get(ref.observationId);
9683
9738
  if (!observation) continue;
9684
- if (result.status === "current" && file) suggestedReads.push(file.path);
9739
+ const excluded = file ? isCodeGraphExcludedPath(file.path, exclude) : false;
9740
+ if (result.status === "current" && file && !excluded) suggestedReads.push(file.path);
9741
+ if (excluded) continue;
9685
9742
  sources.push({
9686
9743
  observationId: observation.id,
9687
9744
  title: observation.title,
@@ -9698,12 +9755,12 @@ function collectGraph(store, projectId, observations2) {
9698
9755
  refs,
9699
9756
  freshness,
9700
9757
  sources,
9701
- suggestedReads: compactSuggestedReads(suggestedReads)
9758
+ suggestedReads: compactSuggestedReads(suggestedReads, 8, exclude)
9702
9759
  };
9703
9760
  }
9704
9761
  function buildProjectContextOverview(input) {
9705
9762
  const active = activeObservations(input.observations, input.project.id);
9706
- const graph = collectGraph(input.store, input.project.id, active);
9763
+ const graph = collectGraph(input.store, input.project.id, active, input.exclude);
9707
9764
  const status = input.store.status(input.project.id);
9708
9765
  return {
9709
9766
  project: input.project,
@@ -9727,7 +9784,7 @@ function buildProjectContextOverview(input) {
9727
9784
  function buildProjectContextExplain(input) {
9728
9785
  const overview = buildProjectContextOverview(input);
9729
9786
  const active = activeObservations(input.observations, input.project.id);
9730
- const graph = collectGraph(input.store, input.project.id, active);
9787
+ const graph = collectGraph(input.store, input.project.id, active, input.exclude);
9731
9788
  return {
9732
9789
  project: input.project,
9733
9790
  sources: graph.sources.sort((a, b) => a.observationId - b.observationId || (a.path ?? "").localeCompare(b.path ?? "")),
@@ -9739,11 +9796,12 @@ var init_project_context = __esm({
9739
9796
  "use strict";
9740
9797
  init_esm_shims();
9741
9798
  init_freshness2();
9799
+ init_exclude();
9742
9800
  }
9743
9801
  });
9744
9802
 
9745
9803
  // src/codegraph/task-lens.ts
9746
- function normalizePath3(path20) {
9804
+ function normalizePath2(path20) {
9747
9805
  return path20.replace(/\\/g, "/");
9748
9806
  }
9749
9807
  function tokenize(text) {
@@ -9773,7 +9831,7 @@ function resolveTaskLens(task) {
9773
9831
  return best.score > 0 ? LENSES[best.id] : LENSES.general;
9774
9832
  }
9775
9833
  function pathKindScore(path20, lens) {
9776
- const normalized = normalizePath3(path20).toLowerCase();
9834
+ const normalized = normalizePath2(path20).toLowerCase();
9777
9835
  const name = normalized.split("/").pop() ?? normalized;
9778
9836
  const inDocs = normalized.startsWith("docs/") || name === "readme.md" || name.includes("readme");
9779
9837
  const isTest = /(^|\/)(tests?|__tests__|spec|fixtures?)\//.test(normalized) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(normalized) || /\.(test|spec)\.py$/.test(normalized);
@@ -9822,7 +9880,7 @@ function sourceTaskMatchScore(source, task) {
9822
9880
  return 0;
9823
9881
  }
9824
9882
  function fallbackPathRank(path20) {
9825
- const normalized = normalizePath3(path20);
9883
+ const normalized = normalizePath2(path20);
9826
9884
  if (normalized.startsWith("src/")) return 0;
9827
9885
  if (normalized.startsWith("tests/") || normalized.startsWith("test/")) return 1;
9828
9886
  if (normalized.startsWith("packages/") && normalized.includes("/src/")) return 2;
@@ -9831,7 +9889,7 @@ function fallbackPathRank(path20) {
9831
9889
  }
9832
9890
  function rankLensPaths(paths, lens, task) {
9833
9891
  const tokens = tokenize(task ?? "");
9834
- return [...new Set(paths.map(normalizePath3))].map((path20, index) => ({
9892
+ return [...new Set(paths.map(normalizePath2))].map((path20, index) => ({
9835
9893
  path: path20,
9836
9894
  index,
9837
9895
  score: pathKindScore(path20, lens) + tokenScore(path20, tokens),
@@ -10085,6 +10143,7 @@ async function buildAutoProjectContext(input) {
10085
10143
  const now = input.now ?? /* @__PURE__ */ new Date();
10086
10144
  const task = input.task?.trim();
10087
10145
  const lens = resolveTaskLens(task);
10146
+ const exclude = input.exclude ?? getResolvedConfig({ projectRoot: input.project.rootPath }).codegraph.excludePatterns;
10088
10147
  const store = new CodeGraphStore();
10089
10148
  await store.init(input.dataDir);
10090
10149
  const initialStatus = store.status(input.project.id);
@@ -10102,7 +10161,8 @@ async function buildAutoProjectContext(input) {
10102
10161
  try {
10103
10162
  const indexed = await indexProjectLite({
10104
10163
  projectId: input.project.id,
10105
- projectRoot: input.project.rootPath
10164
+ projectRoot: input.project.rootPath,
10165
+ exclude
10106
10166
  });
10107
10167
  store.replaceProjectIndex(input.project.id, indexed);
10108
10168
  const backfill = await backfillMissingObservationCodeRefs(
@@ -10122,12 +10182,14 @@ async function buildAutoProjectContext(input) {
10122
10182
  const overview = buildProjectContextOverview({
10123
10183
  project: input.project,
10124
10184
  store,
10125
- observations: input.observations
10185
+ observations: input.observations,
10186
+ exclude
10126
10187
  });
10127
10188
  const explain = buildProjectContextExplain({
10128
10189
  project: input.project,
10129
10190
  store,
10130
- observations: input.observations
10191
+ observations: input.observations,
10192
+ exclude
10131
10193
  });
10132
10194
  return {
10133
10195
  project: input.project,
@@ -10337,6 +10399,7 @@ var init_auto_context = __esm({
10337
10399
  "src/codegraph/auto-context.ts"() {
10338
10400
  "use strict";
10339
10401
  init_esm_shims();
10402
+ init_resolved_config();
10340
10403
  init_binder();
10341
10404
  init_current_facts();
10342
10405
  init_lite_provider();
@@ -10364,9 +10427,6 @@ function tokenize2(text) {
10364
10427
  function timestampOf(observation) {
10365
10428
  return Date.parse(observation.updatedAt ?? observation.createdAt ?? "") || 0;
10366
10429
  }
10367
- function isGeneratedPath2(path20) {
10368
- return /(^|\/)(dist|build|coverage|\.next|\.turbo|node_modules)\//i.test(path20.replace(/\\/g, "/"));
10369
- }
10370
10430
  function relevanceScore(observation, taskTokens) {
10371
10431
  if (taskTokens.length === 0) return 0;
10372
10432
  const title = observation.title.toLowerCase();
@@ -10417,7 +10477,8 @@ function assembleContextPackForTask(input) {
10417
10477
  refs,
10418
10478
  files,
10419
10479
  symbols,
10420
- suggestedVerification: input.suggestedVerification
10480
+ suggestedVerification: input.suggestedVerification,
10481
+ exclude: input.exclude
10421
10482
  });
10422
10483
  }
10423
10484
  function assembleContextPack(input) {
@@ -10436,6 +10497,7 @@ function assembleContextPack(input) {
10436
10497
  observationIdsWithRefs.add(ref.observationId);
10437
10498
  const file = ref.fileId ? files.get(ref.fileId) : void 0;
10438
10499
  const symbol = ref.symbolId ? symbols.get(ref.symbolId) : void 0;
10500
+ if (file && isCodeGraphExcludedPath(file.path, input.exclude)) continue;
10439
10501
  const freshness = evaluateCodeRefFreshness(ref, file, symbol);
10440
10502
  if (freshness.status === "current") {
10441
10503
  const memoryKey = `${observation.id}:${freshness.status}`;
@@ -10501,8 +10563,8 @@ function buildContextPackPrompt(pack) {
10501
10563
  const reliableMemories = pack.memories.filter((memory) => memory.status === "current");
10502
10564
  const unboundMemories = pack.memories.filter((memory) => memory.status === "unbound");
10503
10565
  const lines = ["## Task", pack.task, "", "## Reliable Memories"];
10504
- const visibleCodeFacts = pack.codeFacts.filter((fact) => !isGeneratedPath2(fact.path)).slice(0, 5);
10505
- const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isGeneratedPath2(path20)).slice(0, 5);
10566
+ const visibleCodeFacts = pack.codeFacts.filter((fact) => !isCodeGraphExcludedPath(fact.path)).slice(0, 5);
10567
+ const visibleSuggestedReads = pack.suggestedReads.filter((path20) => !isCodeGraphExcludedPath(path20)).slice(0, 5);
10506
10568
  if (reliableMemories.length === 0) lines.push("- none");
10507
10569
  for (const memory of reliableMemories) {
10508
10570
  lines.push(`- #${memory.id} ${memory.status}: [${memory.type}] ${memory.title} (${memory.reason})`);
@@ -10537,6 +10599,7 @@ var init_context_pack = __esm({
10537
10599
  "use strict";
10538
10600
  init_esm_shims();
10539
10601
  init_freshness2();
10602
+ init_exclude();
10540
10603
  }
10541
10604
  });
10542
10605
 
@@ -14555,7 +14618,7 @@ var init_official_skills = __esm({
14555
14618
  "",
14556
14619
  "## Search Rules",
14557
14620
  "",
14558
- "- 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.",
14621
+ "- 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.",
14559
14622
  "- 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.",
14560
14623
  '- 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.',
14561
14624
  "- Use `memorix_search` for a specific decision, bug, file, or prior change that the project context did not answer.",
@@ -14866,6 +14929,7 @@ var init_audit = __esm({
14866
14929
  var installers_exports = {};
14867
14930
  __export(installers_exports, {
14868
14931
  detectInstalledAgents: () => detectInstalledAgents,
14932
+ getAgentRulesPath: () => getAgentRulesPath,
14869
14933
  getGlobalConfigPath: () => getGlobalConfigPath,
14870
14934
  getHookStatus: () => getHookStatus,
14871
14935
  getProjectConfigPath: () => getProjectConfigPath,
@@ -15732,7 +15796,7 @@ function getAgentRulesContent(agent, scope = "project") {
15732
15796
  let frontmatter = "";
15733
15797
  const contextNoun = scope === "global" ? "workspace" : "project";
15734
15798
  const title = scope === "global" ? "# Memorix \u2014 Memory Tools for Active Workspaces" : "# Memorix \u2014 Project Memory Tools";
15735
- 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.";
15799
+ 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.";
15736
15800
  if (agent === "windsurf") {
15737
15801
  frontmatter = "---\ntrigger: always_on\n---\n\n";
15738
15802
  } else if (agent === "cursor") {
@@ -15750,7 +15814,7 @@ alwaysApply: true
15750
15814
  "",
15751
15815
  "## Start with Memory Autopilot",
15752
15816
  "",
15753
- `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.`,
15817
+ `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.`,
15754
15818
  "",
15755
15819
  '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.',
15756
15820
  "",
@@ -19917,7 +19981,7 @@ The path should point to a directory containing a .git folder.`
19917
19981
  };
19918
19982
  const server = existingServer ?? new McpServer({
19919
19983
  name: "memorix",
19920
- version: true ? "1.1.7" : "1.0.1"
19984
+ version: true ? "1.1.9" : "1.0.1"
19921
19985
  });
19922
19986
  const originalRegisterTool = server.registerTool.bind(server);
19923
19987
  server.registerTool = ((name, ...args) => {
@@ -20619,15 +20683,18 @@ _Search mode: ${getLastSearchMode2(project.id)}_`;
20619
20683
  return withFreshIndex(async () => {
20620
20684
  const { CodeGraphStore: CodeGraphStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
20621
20685
  const { assembleContextPackForTask: assembleContextPackForTask2, buildContextPackPrompt: buildContextPackPrompt2 } = await Promise.resolve().then(() => (init_context_pack(), context_pack_exports));
20686
+ const { getResolvedConfig: getResolvedConfig2 } = await Promise.resolve().then(() => (init_resolved_config(), resolved_config_exports));
20622
20687
  const store = new CodeGraphStore2();
20623
20688
  await store.init(projectDir2);
20689
+ const exclude = getResolvedConfig2({ projectRoot: project.rootPath }).codegraph.excludePatterns;
20624
20690
  const observations2 = getAllObservations().filter((obs) => obs.projectId === project.id && (obs.status ?? "active") === "active").reverse();
20625
20691
  const pack = assembleContextPackForTask2({
20626
20692
  store,
20627
20693
  projectId: project.id,
20628
20694
  task,
20629
20695
  observations: observations2,
20630
- limit: typeof limit === "number" ? limit : 20
20696
+ limit: typeof limit === "number" ? limit : 20,
20697
+ exclude
20631
20698
  });
20632
20699
  const text = buildContextPackPrompt2(pack);
20633
20700
  return {