memorix 1.6.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/TEAM.md +86 -86
  3. package/dist/cli/index.js +317 -62
  4. package/dist/cli/memcode.js +12 -1
  5. package/dist/index.js +56 -9
  6. package/dist/maintenance-runner.js +54 -7
  7. package/dist/media-audio-runner.js +54 -7
  8. package/dist/media-video-runner.js +54 -7
  9. package/dist/memcode-runtime/CHANGELOG.md +24 -0
  10. package/dist/sdk.js +55 -8
  11. package/dist/vector-backfill-runner.js +54 -7
  12. package/docs/AGENT_OPERATOR_PLAYBOOK.md +11 -3
  13. package/docs/API_REFERENCE.md +1 -1
  14. package/docs/DESIGN_DECISIONS.md +357 -357
  15. package/docs/DOCKER.md +5 -1
  16. package/docs/PERFORMANCE.md +2 -2
  17. package/docs/README.md +3 -1
  18. package/docs/SETUP.md +8 -2
  19. package/package.json +1 -1
  20. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  21. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  22. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  23. package/plugins/copilot/memorix/plugin.json +1 -1
  24. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  25. package/plugins/omp/memorix/package.json +1 -1
  26. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  27. package/plugins/pi/memorix/package.json +1 -1
  28. package/server.json +2 -2
  29. package/src/audit/index.ts +156 -156
  30. package/src/cli/commands/agent-integrations.ts +9 -3
  31. package/src/cli/commands/doctor.ts +46 -15
  32. package/src/cli/commands/formation.ts +48 -48
  33. package/src/cli/commands/git-hook-install.ts +111 -111
  34. package/src/cli/commands/handoff.ts +54 -54
  35. package/src/cli/commands/hook.ts +13 -1
  36. package/src/cli/commands/hooks-status.ts +63 -63
  37. package/src/cli/commands/ingest.ts +44 -44
  38. package/src/cli/commands/integrate-shared.ts +15 -15
  39. package/src/cli/commands/lock.ts +82 -82
  40. package/src/cli/commands/message.ts +104 -104
  41. package/src/cli/commands/poll.ts +58 -58
  42. package/src/cli/commands/reasoning.ts +118 -118
  43. package/src/cli/commands/serve-http.ts +68 -7
  44. package/src/cli/commands/skills.ts +114 -114
  45. package/src/cli/commands/task.ts +167 -167
  46. package/src/cli/commands/transfer.ts +47 -47
  47. package/src/cli/heap.ts +76 -0
  48. package/src/cli/index.ts +406 -406
  49. package/src/cli/invocation.ts +7 -4
  50. package/src/cli/tui/ChatView.tsx +234 -234
  51. package/src/cli/tui/CommandBar.tsx +312 -312
  52. package/src/cli/tui/ContextRail.tsx +118 -118
  53. package/src/cli/tui/HeaderBar.tsx +72 -72
  54. package/src/cli/tui/LogoBanner.tsx +51 -51
  55. package/src/cli/tui/index.ts +41 -41
  56. package/src/cli/version.ts +7 -7
  57. package/src/cli/workbench.ts +1 -1
  58. package/src/dashboard/project-classification.ts +64 -64
  59. package/src/embedding/provider.ts +76 -6
  60. package/src/git/hooks-path.ts +85 -85
  61. package/src/hooks/handler.ts +9 -18
  62. package/src/hooks/lifecycle.ts +173 -0
  63. package/src/hooks/pattern-detector.ts +173 -173
  64. package/src/hooks/significance-filter.ts +250 -250
  65. package/src/llm/memory-manager.ts +328 -328
  66. package/src/llm/quality.ts +248 -248
  67. package/src/memory/attribution-guard.ts +249 -249
  68. package/src/memory/disclosure-policy.ts +135 -135
  69. package/src/memory/entity-extractor.ts +197 -197
  70. package/src/memory/formation/evaluate.ts +217 -217
  71. package/src/memory/freshness.ts +122 -122
  72. package/src/memory/graph.ts +197 -197
  73. package/src/memory/refs.ts +94 -94
  74. package/src/memory/secret-filter.ts +79 -79
  75. package/src/orchestrate/adapters/claude-stream.ts +192 -192
  76. package/src/orchestrate/adapters/claude.ts +111 -111
  77. package/src/orchestrate/adapters/codex-stream.ts +134 -134
  78. package/src/orchestrate/adapters/codex.ts +41 -41
  79. package/src/orchestrate/adapters/gemini-stream.ts +166 -166
  80. package/src/orchestrate/adapters/gemini.ts +42 -42
  81. package/src/orchestrate/adapters/index.ts +73 -73
  82. package/src/orchestrate/adapters/opencode-stream.ts +143 -143
  83. package/src/orchestrate/adapters/opencode.ts +47 -47
  84. package/src/orchestrate/adapters/types.ts +77 -77
  85. package/src/orchestrate/capability-router.ts +284 -284
  86. package/src/orchestrate/cost-tracker.ts +219 -219
  87. package/src/orchestrate/error-recovery.ts +191 -191
  88. package/src/orchestrate/evidence.ts +140 -140
  89. package/src/orchestrate/ledger.ts +110 -110
  90. package/src/orchestrate/memorix-bridge.ts +343 -343
  91. package/src/orchestrate/output-budget.ts +80 -80
  92. package/src/orchestrate/permission.ts +152 -152
  93. package/src/orchestrate/pipeline-trace.ts +131 -131
  94. package/src/orchestrate/prompt-builder.ts +155 -155
  95. package/src/orchestrate/ring-buffer.ts +37 -37
  96. package/src/orchestrate/task-graph.ts +389 -389
  97. package/src/project/aliases.ts +374 -374
  98. package/src/rules/adapters/trae.ts +56 -56
  99. package/src/rules/syncer.ts +235 -235
  100. package/src/search/query-expansion.ts +52 -52
  101. package/src/server/formation-timeout.ts +27 -27
  102. package/src/skills/mini-skills.ts +386 -386
  103. package/src/store/chat-store.ts +119 -119
  104. package/src/store/graph-store.ts +249 -249
  105. package/src/store/mini-skill-store.ts +349 -349
  106. package/src/store/persistence-json.ts +212 -212
  107. package/src/store/persistence.ts +291 -291
  108. package/src/store/project-affinity.ts +195 -195
  109. package/src/team/event-bus.ts +76 -76
  110. package/src/team/handoff.ts +161 -161
  111. package/src/team/poll.ts +132 -132
  112. package/src/workspace/mcp-adapters/codex.ts +191 -191
  113. package/src/workspace/mcp-adapters/copilot.ts +105 -105
  114. package/src/workspace/mcp-adapters/cursor.ts +53 -53
  115. package/src/workspace/mcp-adapters/kiro.ts +64 -64
  116. package/src/workspace/mcp-adapters/opencode.ts +123 -123
  117. package/src/workspace/mcp-adapters/trae.ts +134 -134
  118. package/src/workspace/mcp-adapters/windsurf.ts +91 -91
  119. package/src/workspace/sanitizer.ts +60 -60
package/dist/sdk.js CHANGED
@@ -4442,6 +4442,7 @@ __export(provider_exports, {
4442
4442
  MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
4443
4443
  UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
4444
4444
  getEmbeddingProvider: () => getEmbeddingProvider,
4445
+ getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
4445
4446
  isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
4446
4447
  isVectorSearchAvailable: () => isVectorSearchAvailable,
4447
4448
  resetProvider: () => resetProvider,
@@ -4549,13 +4550,36 @@ function isTemporaryEmbeddingFailure(error) {
4549
4550
  if (!(error instanceof Error)) return false;
4550
4551
  return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
4551
4552
  }
4553
+ function classifyEmbeddingFailure(error) {
4554
+ const message = error instanceof Error ? error.message : String(error);
4555
+ if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
4556
+ return "authorization";
4557
+ }
4558
+ if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
4559
+ return "billing";
4560
+ }
4561
+ if (/embedding api timeout|abort/i.test(message)) {
4562
+ return "timeout";
4563
+ }
4564
+ return "upstream";
4565
+ }
4552
4566
  function markTemporaryFailure(reason) {
4553
4567
  provider = null;
4554
4568
  initPromise = null;
4555
4569
  lastInitWasTemporaryFailure = true;
4556
4570
  lastFailureTimestamp = Date.now();
4571
+ lastEmbeddingFailure = {
4572
+ kind: classifyEmbeddingFailure(reason),
4573
+ occurredAt: lastFailureTimestamp
4574
+ };
4557
4575
  const message = reason instanceof Error ? reason.message : String(reason);
4558
- warnOnce(`[memorix] Embedding provider temporarily unavailable at runtime: ${message}`);
4576
+ warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
4577
+ }
4578
+ function markProviderReady(candidate) {
4579
+ provider = wrapProvider(candidate);
4580
+ lastInitWasTemporaryFailure = false;
4581
+ lastEmbeddingFailure = null;
4582
+ return provider;
4559
4583
  }
4560
4584
  async function createFastEmbedProvider() {
4561
4585
  try {
@@ -4671,35 +4695,35 @@ async function getEmbeddingProvider(options = {}) {
4671
4695
  if (mode === "fastembed") {
4672
4696
  const initialized = await createFastEmbedProvider();
4673
4697
  if (!initialized) return null;
4674
- provider = wrapProvider(initialized);
4698
+ provider = markProviderReady(initialized);
4675
4699
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4676
4700
  return provider;
4677
4701
  }
4678
4702
  if (mode === "transformers") {
4679
4703
  const initialized = await createTransformersProvider();
4680
4704
  if (!initialized) return null;
4681
- provider = wrapProvider(initialized);
4705
+ provider = markProviderReady(initialized);
4682
4706
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4683
4707
  return provider;
4684
4708
  }
4685
4709
  if (mode === "api") {
4686
4710
  const initialized = await createAPIProvider(options);
4687
4711
  if (!initialized) return null;
4688
- provider = wrapProvider(initialized);
4712
+ provider = markProviderReady(initialized);
4689
4713
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4690
4714
  return provider;
4691
4715
  }
4692
4716
  if (hasAPIEmbeddingConfig()) {
4693
4717
  const initialized = await createAPIProvider(options);
4694
4718
  if (initialized) {
4695
- provider = wrapProvider(initialized);
4719
+ provider = markProviderReady(initialized);
4696
4720
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4697
4721
  return provider;
4698
4722
  }
4699
4723
  }
4700
4724
  const localFallback = await createLocalFallbackProvider();
4701
4725
  if (localFallback) {
4702
- provider = wrapProvider(localFallback);
4726
+ provider = markProviderReady(localFallback);
4703
4727
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
4704
4728
  return provider;
4705
4729
  }
@@ -4721,6 +4745,27 @@ async function isVectorSearchAvailable() {
4721
4745
  const p = await getEmbeddingProvider();
4722
4746
  return p !== null;
4723
4747
  }
4748
+ function getEmbeddingRuntimeHealth() {
4749
+ const mode = getEmbeddingMode2();
4750
+ if (mode === "off") return { status: "disabled" };
4751
+ if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
4752
+ return {
4753
+ status: "degraded",
4754
+ failure: {
4755
+ kind: lastEmbeddingFailure.kind,
4756
+ occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
4757
+ retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
4758
+ }
4759
+ };
4760
+ }
4761
+ if (provider) {
4762
+ return {
4763
+ status: "ready",
4764
+ provider: { name: provider.name, dimensions: provider.dimensions }
4765
+ };
4766
+ }
4767
+ return { status: "uninitialized" };
4768
+ }
4724
4769
  function isEmbeddingExplicitlyDisabled() {
4725
4770
  return getEmbeddingMode2() === "off";
4726
4771
  }
@@ -4729,10 +4774,11 @@ function resetProvider() {
4729
4774
  initPromise = null;
4730
4775
  lastInitWasTemporaryFailure = false;
4731
4776
  lastFailureTimestamp = 0;
4777
+ lastEmbeddingFailure = null;
4732
4778
  lastEmbeddingWarning = "";
4733
4779
  lastEmbeddingWarningAt = 0;
4734
4780
  }
4735
- var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
4781
+ var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
4736
4782
  var init_provider = __esm({
4737
4783
  "src/embedding/provider.ts"() {
4738
4784
  "use strict";
@@ -4757,6 +4803,7 @@ var init_provider = __esm({
4757
4803
  provider = null;
4758
4804
  initPromise = null;
4759
4805
  lastInitWasTemporaryFailure = false;
4806
+ lastEmbeddingFailure = null;
4760
4807
  lastEmbeddingWarning = "";
4761
4808
  lastEmbeddingWarningAt = 0;
4762
4809
  WARNING_COOLDOWN_MS = 3e4;
@@ -165904,7 +165951,7 @@ The path should point to a directory containing a .git folder.`
165904
165951
  };
165905
165952
  const server = existingServer ?? new McpServer({
165906
165953
  name: "memorix",
165907
- version: true ? "1.6.0" : "1.0.1"
165954
+ version: true ? "1.6.1" : "1.0.1"
165908
165955
  });
165909
165956
  const originalRegisterTool = server.registerTool.bind(server);
165910
165957
  server.registerTool = ((name, ...args) => {
@@ -3206,6 +3206,7 @@ __export(provider_exports, {
3206
3206
  MAX_INLINE_EMBEDDING_BYTES: () => MAX_INLINE_EMBEDDING_BYTES,
3207
3207
  UnsupportedEmbeddingModalityError: () => UnsupportedEmbeddingModalityError,
3208
3208
  getEmbeddingProvider: () => getEmbeddingProvider,
3209
+ getEmbeddingRuntimeHealth: () => getEmbeddingRuntimeHealth,
3209
3210
  isEmbeddingExplicitlyDisabled: () => isEmbeddingExplicitlyDisabled,
3210
3211
  isVectorSearchAvailable: () => isVectorSearchAvailable,
3211
3212
  resetProvider: () => resetProvider,
@@ -3313,13 +3314,36 @@ function isTemporaryEmbeddingFailure(error) {
3313
3314
  if (!(error instanceof Error)) return false;
3314
3315
  return /embedding api error \(401\)/i.test(error.message) || /invalid_api_key/i.test(error.message) || /incorrect api key/i.test(error.message) || /unauthorized/i.test(error.message) || /embedding api timeout/i.test(error.message) || /embedding api error \((402|429|5\d\d)\)/i.test(error.message) || /quota exceeded/i.test(error.message) || /account balance/i.test(error.message) || /fetch failed/i.test(error.message) || /econnreset/i.test(error.message) || /econnrefused/i.test(error.message) || /temporarily unavailable/i.test(error.message);
3315
3316
  }
3317
+ function classifyEmbeddingFailure(error) {
3318
+ const message = error instanceof Error ? error.message : String(error);
3319
+ if (/embedding api error \(401\)|invalid_api_key|incorrect api key|unauthorized/i.test(message)) {
3320
+ return "authorization";
3321
+ }
3322
+ if (/embedding api error \(402\)|quota exceeded|account balance/i.test(message)) {
3323
+ return "billing";
3324
+ }
3325
+ if (/embedding api timeout|abort/i.test(message)) {
3326
+ return "timeout";
3327
+ }
3328
+ return "upstream";
3329
+ }
3316
3330
  function markTemporaryFailure(reason) {
3317
3331
  provider = null;
3318
3332
  initPromise = null;
3319
3333
  lastInitWasTemporaryFailure = true;
3320
3334
  lastFailureTimestamp = Date.now();
3335
+ lastEmbeddingFailure = {
3336
+ kind: classifyEmbeddingFailure(reason),
3337
+ occurredAt: lastFailureTimestamp
3338
+ };
3321
3339
  const message = reason instanceof Error ? reason.message : String(reason);
3322
- warnOnce(`[memorix] Embedding provider temporarily unavailable at runtime: ${message}`);
3340
+ warnOnce(`[memorix] Embedding provider unavailable at runtime: ${message}`);
3341
+ }
3342
+ function markProviderReady(candidate) {
3343
+ provider = wrapProvider(candidate);
3344
+ lastInitWasTemporaryFailure = false;
3345
+ lastEmbeddingFailure = null;
3346
+ return provider;
3323
3347
  }
3324
3348
  async function createFastEmbedProvider() {
3325
3349
  try {
@@ -3435,35 +3459,35 @@ async function getEmbeddingProvider(options = {}) {
3435
3459
  if (mode === "fastembed") {
3436
3460
  const initialized = await createFastEmbedProvider();
3437
3461
  if (!initialized) return null;
3438
- provider = wrapProvider(initialized);
3462
+ provider = markProviderReady(initialized);
3439
3463
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
3440
3464
  return provider;
3441
3465
  }
3442
3466
  if (mode === "transformers") {
3443
3467
  const initialized = await createTransformersProvider();
3444
3468
  if (!initialized) return null;
3445
- provider = wrapProvider(initialized);
3469
+ provider = markProviderReady(initialized);
3446
3470
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
3447
3471
  return provider;
3448
3472
  }
3449
3473
  if (mode === "api") {
3450
3474
  const initialized = await createAPIProvider(options);
3451
3475
  if (!initialized) return null;
3452
- provider = wrapProvider(initialized);
3476
+ provider = markProviderReady(initialized);
3453
3477
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
3454
3478
  return provider;
3455
3479
  }
3456
3480
  if (hasAPIEmbeddingConfig()) {
3457
3481
  const initialized = await createAPIProvider(options);
3458
3482
  if (initialized) {
3459
- provider = wrapProvider(initialized);
3483
+ provider = markProviderReady(initialized);
3460
3484
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
3461
3485
  return provider;
3462
3486
  }
3463
3487
  }
3464
3488
  const localFallback = await createLocalFallbackProvider();
3465
3489
  if (localFallback) {
3466
- provider = wrapProvider(localFallback);
3490
+ provider = markProviderReady(localFallback);
3467
3491
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
3468
3492
  return provider;
3469
3493
  }
@@ -3485,6 +3509,27 @@ async function isVectorSearchAvailable() {
3485
3509
  const p = await getEmbeddingProvider();
3486
3510
  return p !== null;
3487
3511
  }
3512
+ function getEmbeddingRuntimeHealth() {
3513
+ const mode = getEmbeddingMode2();
3514
+ if (mode === "off") return { status: "disabled" };
3515
+ if (lastInitWasTemporaryFailure && lastEmbeddingFailure) {
3516
+ return {
3517
+ status: "degraded",
3518
+ failure: {
3519
+ kind: lastEmbeddingFailure.kind,
3520
+ occurredAt: new Date(lastEmbeddingFailure.occurredAt).toISOString(),
3521
+ retryAfterMs: Math.max(0, RETRY_COOLDOWN_MS - (Date.now() - lastEmbeddingFailure.occurredAt))
3522
+ }
3523
+ };
3524
+ }
3525
+ if (provider) {
3526
+ return {
3527
+ status: "ready",
3528
+ provider: { name: provider.name, dimensions: provider.dimensions }
3529
+ };
3530
+ }
3531
+ return { status: "uninitialized" };
3532
+ }
3488
3533
  function isEmbeddingExplicitlyDisabled() {
3489
3534
  return getEmbeddingMode2() === "off";
3490
3535
  }
@@ -3493,10 +3538,11 @@ function resetProvider() {
3493
3538
  initPromise = null;
3494
3539
  lastInitWasTemporaryFailure = false;
3495
3540
  lastFailureTimestamp = 0;
3541
+ lastEmbeddingFailure = null;
3496
3542
  lastEmbeddingWarning = "";
3497
3543
  lastEmbeddingWarningAt = 0;
3498
3544
  }
3499
- var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
3545
+ var EmbeddingInputError, UnsupportedEmbeddingModalityError, MAX_INLINE_EMBEDDING_BYTES, provider, initPromise, lastInitWasTemporaryFailure, lastEmbeddingFailure, lastEmbeddingWarning, lastEmbeddingWarningAt, WARNING_COOLDOWN_MS, RETRY_COOLDOWN_MS, lastFailureTimestamp;
3500
3546
  var init_provider = __esm({
3501
3547
  "src/embedding/provider.ts"() {
3502
3548
  "use strict";
@@ -3521,6 +3567,7 @@ var init_provider = __esm({
3521
3567
  provider = null;
3522
3568
  initPromise = null;
3523
3569
  lastInitWasTemporaryFailure = false;
3570
+ lastEmbeddingFailure = null;
3524
3571
  lastEmbeddingWarning = "";
3525
3572
  lastEmbeddingWarningAt = 0;
3526
3573
  WARNING_COOLDOWN_MS = 3e4;
@@ -58,7 +58,7 @@ An unbound terminal is intentionally project-scoped: it reads and writes project
58
58
 
59
59
  Long-term memory is a reviewed layer, not a generic global note store. `memorix memory long-term add` creates a candidate; `qualify` and `approve` are explicit audit transitions before it can appear in a bounded task Workset. A project-derived observation, code fact, Git fact, test, session, Claim, or workflow stays project-bound. Only manual or user-confirmed `user + portable` records can cross local projects for the same local installation identity. When one is task-matched in a Workset, it is intentionally usable background even if its origin differs; use its `durable:<id>` reference with `memorix_detail` only when the full record is needed. Use `archive` or `supersede` when a durable item is no longer current.
60
60
 
61
- `--cwd <git-project>` is the canonical way to run direct CLI work from outside a repository. It changes the command's project anchor only; Git remains the source of truth for final project identity.
61
+ `--cwd <git-project>` is the canonical way to run direct CLI work from outside a repository. It changes the command's project anchor only; Git remains the source of truth for final project identity. Existing directories are canonicalized to their real filesystem paths before binding, which prevents macOS aliases such as `/var` and `/private/var` from splitting one project or hiding a Claude local MCP entry.
62
62
 
63
63
  Use MCP when:
64
64
 
@@ -164,7 +164,12 @@ Do not assume the HTTP connection alone tells Memorix which project the user mea
164
164
 
165
165
  The HTTP service is normally started with `memorix background start`; the same project-binding rules apply when you run `memorix serve-http --port 3211` in the foreground.
166
166
 
167
- HTTP MCP sessions idle out after 30 minutes by default. If the user's HTTP MCP client is sensitive to stale session IDs after long idle periods, set `MEMORIX_SESSION_TIMEOUT_MS` before starting or restarting the service. Example: `MEMORIX_SESSION_TIMEOUT_MS=86400000` keeps sessions alive for 24 hours.
167
+ HTTP MCP sessions idle out after 12 hours by default. An expired session now
168
+ receives a fast `404` reinitialize hint instead of a generic transport failure.
169
+ If the user's HTTP MCP client needs a longer idle period, set
170
+ `MEMORIX_SESSION_TIMEOUT_MS` before starting or restarting the service.
171
+ Example: `MEMORIX_SESSION_TIMEOUT_MS=86400000` keeps sessions alive for 24
172
+ hours. Set it to `0` only when the host has its own reliable session cleanup.
168
173
 
169
174
  ### Do not confuse project config and global config
170
175
 
@@ -702,7 +707,10 @@ If it shows "Not running" or "dead":
702
707
  memorix background ensure
703
708
  ```
704
709
 
705
- If the client is connected but starts failing after roughly 30 minutes of no Memorix tool use, check for stale HTTP session expiry rather than treating it as project binding failure. Restart the service with a longer idle timeout:
710
+ If the client is connected but starts failing after a long inactive period,
711
+ check for the explicit stale-session `404` reinitialize hint rather than
712
+ treating it as a project-binding failure. The default idle window is 12 hours;
713
+ restart with a longer window only when the client genuinely needs it:
706
714
 
707
715
  ```powershell
708
716
  $env:MEMORIX_SESSION_TIMEOUT_MS = "86400000"
@@ -652,7 +652,7 @@ Coordination state is opt-in project state for tasks, handoff messages, locks, a
652
652
 
653
653
  Runtime environment:
654
654
 
655
- - `MEMORIX_SESSION_TIMEOUT_MS` — HTTP MCP session idle timeout in milliseconds. Default: `1800000` (30 minutes). Increase this for clients that do not transparently reinitialize after stale HTTP session IDs, for example `86400000` for 24 hours.
655
+ - `MEMORIX_SESSION_TIMEOUT_MS` — HTTP MCP session idle timeout in milliseconds. Default: `43200000` (12 hours). Expired session IDs receive a fast `404` with a reinitialize hint. Increase this for long-lived clients, for example `86400000` for 24 hours; set `0` only when the host provides reliable lifecycle cleanup.
656
656
 
657
657
  ### `team_manage`
658
658