basic-memory 0.17.2__tar.gz → 0.17.4__tar.gz

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 (443) hide show
  1. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/claude-code-review.yml +1 -0
  2. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/test.yml +55 -1
  3. {basic_memory-0.17.2 → basic_memory-0.17.4}/CHANGELOG.md +60 -0
  4. {basic_memory-0.17.2 → basic_memory-0.17.4}/CLAUDE.md +26 -4
  5. {basic_memory-0.17.2 → basic_memory-0.17.4}/PKG-INFO +2 -2
  6. basic_memory-0.17.4/docs/ARCHITECTURE.md +412 -0
  7. basic_memory-0.17.4/docs/testing-coverage.md +30 -0
  8. {basic_memory-0.17.2 → basic_memory-0.17.4}/justfile +27 -12
  9. {basic_memory-0.17.2 → basic_memory-0.17.4}/pyproject.toml +8 -4
  10. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/__init__.py +1 -1
  11. basic_memory-0.17.4/src/basic_memory/alembic/versions/6830751f5fb6_merge_multiple_heads.py +24 -0
  12. basic_memory-0.17.4/src/basic_memory/alembic/versions/g9a0b3c4d5e6_add_external_id_to_project_and_entity.py +173 -0
  13. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/app.py +31 -43
  14. basic_memory-0.17.4/src/basic_memory/api/container.py +133 -0
  15. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/knowledge_router.py +4 -3
  16. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/project_router.py +17 -5
  17. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/resource_router.py +4 -4
  18. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/directory_router.py +13 -13
  19. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/importer_router.py +18 -19
  20. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/knowledge_router.py +120 -106
  21. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/memory_router.py +11 -11
  22. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/project_router.py +88 -71
  23. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/prompt_router.py +16 -17
  24. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/resource_router.py +59 -59
  25. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/search_router.py +11 -11
  26. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/app.py +11 -5
  27. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/auth.py +27 -4
  28. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/api_client.py +20 -5
  29. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/cloud_utils.py +13 -6
  30. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/rclone_commands.py +47 -21
  31. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/upload.py +10 -3
  32. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/command_utils.py +25 -3
  33. basic_memory-0.17.4/src/basic_memory/cli/commands/db.py +103 -0
  34. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/import_chatgpt.py +10 -7
  35. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/import_claude_conversations.py +10 -7
  36. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/import_claude_projects.py +10 -7
  37. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/import_memory_json.py +10 -7
  38. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/project.py +2 -2
  39. basic_memory-0.17.4/src/basic_memory/cli/container.py +84 -0
  40. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/config.py +4 -4
  41. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/db.py +31 -7
  42. basic_memory-0.17.4/src/basic_memory/deps/__init__.py +293 -0
  43. basic_memory-0.17.4/src/basic_memory/deps/config.py +26 -0
  44. basic_memory-0.17.4/src/basic_memory/deps/db.py +56 -0
  45. basic_memory-0.17.4/src/basic_memory/deps/importers.py +200 -0
  46. basic_memory-0.17.4/src/basic_memory/deps/projects.py +238 -0
  47. basic_memory-0.17.4/src/basic_memory/deps/repositories.py +179 -0
  48. basic_memory-0.17.4/src/basic_memory/deps/services.py +480 -0
  49. basic_memory-0.17.4/src/basic_memory/deps.py +16 -0
  50. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/file_utils.py +4 -4
  51. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/ignore_utils.py +5 -5
  52. basic_memory-0.17.4/src/basic_memory/importers/base.py +100 -0
  53. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/chatgpt_importer.py +17 -4
  54. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/claude_conversations_importer.py +23 -11
  55. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/claude_projects_importer.py +50 -14
  56. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/memory_json_importer.py +36 -16
  57. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/markdown_processor.py +48 -4
  58. basic_memory-0.17.4/src/basic_memory/mcp/clients/__init__.py +28 -0
  59. basic_memory-0.17.4/src/basic_memory/mcp/clients/directory.py +70 -0
  60. basic_memory-0.17.4/src/basic_memory/mcp/clients/knowledge.py +176 -0
  61. basic_memory-0.17.4/src/basic_memory/mcp/clients/memory.py +120 -0
  62. basic_memory-0.17.4/src/basic_memory/mcp/clients/project.py +89 -0
  63. basic_memory-0.17.4/src/basic_memory/mcp/clients/resource.py +71 -0
  64. basic_memory-0.17.4/src/basic_memory/mcp/clients/search.py +65 -0
  65. basic_memory-0.17.4/src/basic_memory/mcp/container.py +110 -0
  66. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/project_context.py +36 -34
  67. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +2 -2
  68. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/recent_activity.py +2 -2
  69. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/utils.py +3 -3
  70. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/server.py +16 -30
  71. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/build_context.py +12 -12
  72. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/canvas.py +6 -6
  73. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/chatgpt_tools.py +1 -1
  74. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/delete_note.py +18 -11
  75. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/edit_note.py +10 -9
  76. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/list_directory.py +5 -16
  77. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/move_note.py +29 -31
  78. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/project_management.py +25 -22
  79. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/read_content.py +2 -2
  80. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/read_note.py +11 -13
  81. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/recent_activity.py +28 -35
  82. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/search.py +15 -9
  83. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/utils.py +10 -10
  84. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/write_note.py +16 -16
  85. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/models/knowledge.py +7 -1
  86. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/models/project.py +7 -1
  87. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/models/search.py +9 -0
  88. basic_memory-0.17.4/src/basic_memory/project_resolver.py +222 -0
  89. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/entity_repository.py +34 -16
  90. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/postgres_search_repository.py +92 -20
  91. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/project_repository.py +12 -0
  92. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/relation_repository.py +4 -4
  93. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/search_repository.py +11 -4
  94. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/search_repository_base.py +2 -2
  95. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/sqlite_search_repository.py +5 -7
  96. basic_memory-0.17.4/src/basic_memory/runtime.py +61 -0
  97. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/base.py +2 -2
  98. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/directory.py +2 -1
  99. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/memory.py +2 -2
  100. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/project_info.py +1 -0
  101. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/response.py +84 -27
  102. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/sync_report.py +1 -1
  103. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/v2/entity.py +13 -9
  104. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/v2/resource.py +2 -1
  105. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/context_service.py +5 -5
  106. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/directory_service.py +13 -11
  107. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/file_service.py +12 -8
  108. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/project_service.py +33 -25
  109. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/search_service.py +29 -11
  110. basic_memory-0.17.4/src/basic_memory/sync/__init__.py +7 -0
  111. basic_memory-0.17.4/src/basic_memory/sync/coordinator.py +160 -0
  112. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/sync/sync_service.py +9 -3
  113. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/sync/watch_service.py +12 -7
  114. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/utils.py +5 -5
  115. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/conftest.py +2 -0
  116. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_lifespan_shutdown_sync_task_cancellation_integration.py +22 -11
  117. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_write_note_integration.py +1 -0
  118. basic_memory-0.17.4/tests/api/test_api_container.py +62 -0
  119. basic_memory-0.17.4/tests/api/test_async_client.py +53 -0
  120. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_directory_router.py +0 -199
  121. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_knowledge_router.py +0 -36
  122. basic_memory-0.17.4/tests/api/test_management_router.py +123 -0
  123. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_relation_background_resolution.py +19 -9
  124. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/conftest.py +3 -3
  125. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_knowledge_router.py +64 -62
  126. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_project_router.py +55 -51
  127. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_resource_router.py +28 -22
  128. basic_memory-0.17.4/tests/cli/cloud/test_cloud_api_client_and_utils.py +161 -0
  129. basic_memory-0.17.4/tests/cli/cloud/test_rclone_config_and_bmignore_filters.py +80 -0
  130. basic_memory-0.17.4/tests/cli/cloud/test_upload_path.py +73 -0
  131. basic_memory-0.17.4/tests/cli/test_auth_cli_auth.py +147 -0
  132. basic_memory-0.17.4/tests/cli/test_cli_container.py +96 -0
  133. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_cli_tool_exit.py +20 -3
  134. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_cli_tools.py +44 -41
  135. basic_memory-0.17.4/tests/cli/test_cloud_authentication.py +225 -0
  136. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_import_memory_json.py +5 -3
  137. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_project_add_with_local_path.py +35 -23
  138. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_upload.py +84 -182
  139. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/conftest.py +30 -0
  140. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/importers/test_conversation_indexing.py +4 -2
  141. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/importers/test_importer_base.py +28 -43
  142. basic_memory-0.17.4/tests/mcp/clients/__init__.py +0 -0
  143. basic_memory-0.17.4/tests/mcp/clients/test_clients.py +312 -0
  144. basic_memory-0.17.4/tests/mcp/test_async_client_modes.py +82 -0
  145. basic_memory-0.17.4/tests/mcp/test_mcp_container.py +93 -0
  146. basic_memory-0.17.4/tests/mcp/test_project_context.py +105 -0
  147. basic_memory-0.17.4/tests/mcp/test_recent_activity_prompt_modes.py +101 -0
  148. basic_memory-0.17.4/tests/mcp/test_server_lifespan_branches.py +36 -0
  149. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_move_note.py +28 -66
  150. basic_memory-0.17.4/tests/mcp/test_tool_project_management.py +51 -0
  151. basic_memory-0.17.4/tests/mcp/test_tool_read_content.py +170 -0
  152. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_read_note.py +83 -25
  153. basic_memory-0.17.4/tests/mcp/test_tool_recent_activity.py +412 -0
  154. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_search.py +56 -20
  155. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_utils.py +54 -31
  156. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_view_note.py +12 -57
  157. basic_memory-0.17.4/tests/mcp/tools/test_chatgpt_tools.py +215 -0
  158. basic_memory-0.17.4/tests/repository/test_postgres_search_repository.py +195 -0
  159. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_search_repository.py +163 -12
  160. basic_memory-0.17.4/tests/schemas/test_relation_response_reference_resolution.py +42 -0
  161. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_schemas.py +43 -0
  162. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_entity_service.py +6 -6
  163. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_file_service.py +37 -19
  164. basic_memory-0.17.4/tests/services/test_initialization.py +120 -0
  165. basic_memory-0.17.4/tests/services/test_initialization_cloud_mode_branches.py +23 -0
  166. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_project_service.py +4 -12
  167. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_project_service_operations.py +0 -38
  168. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_search_service.py +8 -40
  169. basic_memory-0.17.4/tests/sync/test_coordinator.py +135 -0
  170. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_sync_service.py +74 -503
  171. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_watch_service.py +10 -8
  172. basic_memory-0.17.4/tests/sync/test_watch_service_atomic_adds.py +53 -0
  173. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_watch_service_edge_cases.py +5 -15
  174. basic_memory-0.17.4/tests/sync/test_watch_service_reload.py +259 -0
  175. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/test_deps.py +26 -0
  176. basic_memory-0.17.4/tests/test_project_resolver.py +209 -0
  177. basic_memory-0.17.4/tests/test_rclone_commands.py +460 -0
  178. basic_memory-0.17.4/tests/test_runtime.py +53 -0
  179. basic_memory-0.17.4/tests/test_telemetry.py +268 -0
  180. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_timezone_utils.py +6 -10
  181. {basic_memory-0.17.2 → basic_memory-0.17.4}/uv.lock +993 -985
  182. basic_memory-0.17.2/src/basic_memory/cli/commands/db.py +0 -44
  183. basic_memory-0.17.2/src/basic_memory/deps.py +0 -705
  184. basic_memory-0.17.2/src/basic_memory/importers/base.py +0 -79
  185. basic_memory-0.17.2/src/basic_memory/sync/__init__.py +0 -6
  186. basic_memory-0.17.2/tests/api/test_async_client.py +0 -56
  187. basic_memory-0.17.2/tests/api/test_management_router.py +0 -211
  188. basic_memory-0.17.2/tests/cli/test_cloud_authentication.py +0 -239
  189. basic_memory-0.17.2/tests/mcp/test_project_context.py +0 -144
  190. basic_memory-0.17.2/tests/mcp/test_tool_read_content.py +0 -495
  191. basic_memory-0.17.2/tests/mcp/test_tool_recent_activity.py +0 -135
  192. basic_memory-0.17.2/tests/mcp/tools/test_chatgpt_tools.py +0 -228
  193. basic_memory-0.17.2/tests/services/test_initialization.py +0 -122
  194. basic_memory-0.17.2/tests/sync/test_watch_service_reload.py +0 -252
  195. basic_memory-0.17.2/tests/test_rclone_commands.py +0 -647
  196. basic_memory-0.17.2/tests/test_telemetry.py +0 -276
  197. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/release/beta.md +0 -0
  198. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/release/changelog.md +0 -0
  199. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/release/release-check.md +0 -0
  200. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/release/release.md +0 -0
  201. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/spec.md +0 -0
  202. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/commands/test-live.md +0 -0
  203. {basic_memory-0.17.2 → basic_memory-0.17.4}/.claude/settings.json +0 -0
  204. {basic_memory-0.17.2 → basic_memory-0.17.4}/.dockerignore +0 -0
  205. {basic_memory-0.17.2 → basic_memory-0.17.4}/.env.example +0 -0
  206. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  207. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  208. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  209. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  210. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/dependabot.yml +0 -0
  211. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/claude-issue-triage.yml +0 -0
  212. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/claude.yml +0 -0
  213. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/dev-release.yml +0 -0
  214. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/docker.yml +0 -0
  215. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/pr-title.yml +0 -0
  216. {basic_memory-0.17.2 → basic_memory-0.17.4}/.github/workflows/release.yml +0 -0
  217. {basic_memory-0.17.2 → basic_memory-0.17.4}/.gitignore +0 -0
  218. {basic_memory-0.17.2 → basic_memory-0.17.4}/.python-version +0 -0
  219. {basic_memory-0.17.2 → basic_memory-0.17.4}/CITATION.cff +0 -0
  220. {basic_memory-0.17.2 → basic_memory-0.17.4}/CLA.md +0 -0
  221. {basic_memory-0.17.2 → basic_memory-0.17.4}/CODE_OF_CONDUCT.md +0 -0
  222. {basic_memory-0.17.2 → basic_memory-0.17.4}/CONTRIBUTING.md +0 -0
  223. {basic_memory-0.17.2 → basic_memory-0.17.4}/Dockerfile +0 -0
  224. {basic_memory-0.17.2 → basic_memory-0.17.4}/LICENSE +0 -0
  225. {basic_memory-0.17.2 → basic_memory-0.17.4}/README.md +0 -0
  226. {basic_memory-0.17.2 → basic_memory-0.17.4}/SECURITY.md +0 -0
  227. {basic_memory-0.17.2 → basic_memory-0.17.4}/docker-compose-postgres.yml +0 -0
  228. {basic_memory-0.17.2 → basic_memory-0.17.4}/docker-compose.yml +0 -0
  229. {basic_memory-0.17.2 → basic_memory-0.17.4}/docs/Docker.md +0 -0
  230. {basic_memory-0.17.2 → basic_memory-0.17.4}/docs/ai-assistant-guide-extended.md +0 -0
  231. {basic_memory-0.17.2 → basic_memory-0.17.4}/docs/character-handling.md +0 -0
  232. {basic_memory-0.17.2 → basic_memory-0.17.4}/docs/cloud-cli.md +0 -0
  233. {basic_memory-0.17.2 → basic_memory-0.17.4}/llms-install.md +0 -0
  234. {basic_memory-0.17.2 → basic_memory-0.17.4}/smithery.yaml +0 -0
  235. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
  236. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
  237. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
  238. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
  239. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
  240. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
  241. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
  242. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
  243. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
  244. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
  245. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
  246. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
  247. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-2 Slash Commands Reference.md +0 -0
  248. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
  249. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-3 Agent Definitions.md +0 -0
  250. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
  251. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
  252. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
  253. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
  254. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-8 TigrisFS Integration.md +0 -0
  255. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
  256. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
  257. {basic_memory-0.17.2 → basic_memory-0.17.4}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
  258. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/alembic.ini +0 -0
  259. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/env.py +0 -0
  260. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/migrations.py +0 -0
  261. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/script.py.mako +0 -0
  262. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/314f1ea54dc4_add_postgres_full_text_search_support_.py +0 -0
  263. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  264. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  265. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  266. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  267. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  268. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  269. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/a2b3c4d5e6f7_add_search_index_entity_cascade.py +0 -0
  270. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  271. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  272. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  273. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/alembic/versions/f8a9b2c3d4e5_add_pg_trgm_for_fuzzy_link_resolution.py +0 -0
  274. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/__init__.py +0 -0
  275. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/__init__.py +0 -0
  276. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/directory_router.py +0 -0
  277. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/importer_router.py +0 -0
  278. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/management_router.py +0 -0
  279. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/memory_router.py +0 -0
  280. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/prompt_router.py +0 -0
  281. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/search_router.py +0 -0
  282. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/routers/utils.py +0 -0
  283. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/template_loader.py +0 -0
  284. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/__init__.py +0 -0
  285. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/api/v2/routers/__init__.py +0 -0
  286. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/__init__.py +0 -0
  287. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/__init__.py +0 -0
  288. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  289. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  290. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  291. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  292. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/rclone_installer.py +0 -0
  293. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
  294. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/format.py +0 -0
  295. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/mcp.py +0 -0
  296. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/status.py +0 -0
  297. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/telemetry.py +0 -0
  298. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/commands/tool.py +0 -0
  299. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/cli/main.py +0 -0
  300. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/__init__.py +0 -0
  301. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/importers/utils.py +0 -0
  302. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/__init__.py +0 -0
  303. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/entity_parser.py +0 -0
  304. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/plugins.py +0 -0
  305. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/schemas.py +0 -0
  306. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/markdown/utils.py +0 -0
  307. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/__init__.py +0 -0
  308. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/async_client.py +0 -0
  309. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  310. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  311. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/prompts/search.py +0 -0
  312. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  313. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/resources/project_info.py +0 -0
  314. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/__init__.py +0 -0
  315. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/mcp/tools/view_note.py +0 -0
  316. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/models/__init__.py +0 -0
  317. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/models/base.py +0 -0
  318. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/__init__.py +0 -0
  319. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/observation_repository.py +0 -0
  320. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/project_info_repository.py +0 -0
  321. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/repository.py +0 -0
  322. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/repository/search_index_row.py +0 -0
  323. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/__init__.py +0 -0
  324. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/cloud.py +0 -0
  325. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/delete.py +0 -0
  326. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/importer.py +0 -0
  327. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/prompt.py +0 -0
  328. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/request.py +0 -0
  329. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/search.py +0 -0
  330. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/schemas/v2/__init__.py +0 -0
  331. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/__init__.py +0 -0
  332. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/entity_service.py +0 -0
  333. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/exceptions.py +0 -0
  334. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/initialization.py +0 -0
  335. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/link_resolver.py +0 -0
  336. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/services/service.py +0 -0
  337. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/sync/background_sync.py +0 -0
  338. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/telemetry.py +0 -0
  339. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  340. {basic_memory-0.17.2 → basic_memory-0.17.4}/src/basic_memory/templates/prompts/search.hbs +0 -0
  341. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/BENCHMARKS.md +0 -0
  342. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/cli/test_project_commands_integration.py +0 -0
  343. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/cli/test_version_integration.py +0 -0
  344. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_build_context_underscore.py +0 -0
  345. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_build_context_validation.py +0 -0
  346. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  347. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  348. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_delete_note_integration.py +0 -0
  349. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_edit_note_integration.py +0 -0
  350. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_list_directory_integration.py +0 -0
  351. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_move_note_integration.py +0 -0
  352. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_project_management_integration.py +0 -0
  353. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  354. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_read_content_integration.py +0 -0
  355. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_read_note_integration.py +0 -0
  356. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_search_integration.py +0 -0
  357. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  358. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/test_db_wal_mode.py +0 -0
  359. {basic_memory-0.17.2 → basic_memory-0.17.4}/test-int/test_disable_permalinks_integration.py +0 -0
  360. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/Non-MarkdownFileSupport.pdf +0 -0
  361. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/README.md +0 -0
  362. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/Screenshot.png +0 -0
  363. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/__init__.py +0 -0
  364. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/conftest.py +0 -0
  365. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_continue_conversation_template.py +0 -0
  366. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_importer_router.py +0 -0
  367. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_memory_router.py +0 -0
  368. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_project_router.py +0 -0
  369. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_project_router_operations.py +0 -0
  370. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_prompt_router.py +0 -0
  371. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_resource_router.py +0 -0
  372. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_search_router.py +0 -0
  373. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_search_template.py +0 -0
  374. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_template_loader.py +0 -0
  375. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/test_template_loader_helpers.py +0 -0
  376. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/__init__.py +0 -0
  377. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_directory_router.py +0 -0
  378. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_importer_router.py +0 -0
  379. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_memory_router.py +0 -0
  380. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_prompt_router.py +0 -0
  381. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/api/v2/test_search_router.py +0 -0
  382. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/conftest.py +0 -0
  383. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_cli_exit.py +0 -0
  384. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_ignore_utils.py +0 -0
  385. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_import_chatgpt.py +0 -0
  386. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_import_claude_conversations.py +0 -0
  387. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/cli/test_import_claude_projects.py +0 -0
  388. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  389. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/importers/test_importer_utils.py +0 -0
  390. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/__init__.py +0 -0
  391. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  392. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_entity_parser.py +0 -0
  393. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  394. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_markdown_plugins.py +0 -0
  395. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_markdown_processor.py +0 -0
  396. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_observation_edge_cases.py +0 -0
  397. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_parser_edge_cases.py +0 -0
  398. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_relation_edge_cases.py +0 -0
  399. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/markdown/test_task_detection.py +0 -0
  400. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/conftest.py +0 -0
  401. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  402. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  403. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_prompts.py +0 -0
  404. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_resources.py +0 -0
  405. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_build_context.py +0 -0
  406. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_canvas.py +0 -0
  407. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_delete_note.py +0 -0
  408. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_edit_note.py +0 -0
  409. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_list_directory.py +0 -0
  410. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_resource.py +0 -0
  411. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_write_note.py +0 -0
  412. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/mcp/test_tool_write_note_kebab_filenames.py +0 -0
  413. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_entity_repository.py +0 -0
  414. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_entity_repository_upsert.py +0 -0
  415. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  416. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_observation_repository.py +0 -0
  417. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_project_info_repository.py +0 -0
  418. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_project_repository.py +0 -0
  419. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_relation_repository.py +0 -0
  420. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_repository.py +0 -0
  421. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  422. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  423. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_memory_serialization.py +0 -0
  424. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_memory_url.py +0 -0
  425. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_memory_url_validation.py +0 -0
  426. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/schemas/test_search.py +0 -0
  427. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_context_service.py +0 -0
  428. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_directory_service.py +0 -0
  429. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  430. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_link_resolver.py +0 -0
  431. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/services/test_project_removal_bug.py +0 -0
  432. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_character_conflicts.py +0 -0
  433. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_sync_service_incremental.py +0 -0
  434. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_sync_wikilink_issue.py +0 -0
  435. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/sync/test_tmp_files.py +0 -0
  436. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/test_config.py +0 -0
  437. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/test_production_cascade_delete.py +0 -0
  438. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_file_utils.py +0 -0
  439. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  440. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_parse_tags.py +0 -0
  441. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_permalink_formatting.py +0 -0
  442. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_utf8_handling.py +0 -0
  443. {basic_memory-0.17.2 → basic_memory-0.17.4}/tests/utils/test_validate_project_path.py +0 -0
@@ -54,6 +54,7 @@ jobs:
54
54
  - [ ] Unit tests for new functions/methods
55
55
  - [ ] Integration tests for new MCP tools
56
56
  - [ ] Test coverage for edge cases
57
+ - [ ] **100% test coverage maintained** (use `# pragma: no cover` only for truly hard-to-test code)
57
58
  - [ ] Documentation updated (README, docstrings)
58
59
  - [ ] CLAUDE.md updated if conventions change
59
60
 
@@ -110,4 +110,58 @@ jobs:
110
110
  - name: Run tests (Postgres via testcontainers)
111
111
  run: |
112
112
  uv pip install pytest pytest-cov
113
- just test-postgres
113
+ just test-postgres
114
+
115
+ coverage:
116
+ name: Coverage Summary (combined, Python 3.12)
117
+ runs-on: ubuntu-latest
118
+
119
+ steps:
120
+ - uses: actions/checkout@v4
121
+ with:
122
+ submodules: true
123
+
124
+ - name: Set up Python 3.12
125
+ uses: actions/setup-python@v4
126
+ with:
127
+ python-version: "3.12"
128
+ cache: "pip"
129
+
130
+ - name: Install uv
131
+ run: |
132
+ pip install uv
133
+
134
+ - name: Install just
135
+ run: |
136
+ curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin
137
+
138
+ - name: Create virtual env
139
+ run: |
140
+ uv venv
141
+
142
+ - name: Install dependencies
143
+ run: |
144
+ uv pip install -e .[dev]
145
+
146
+ - name: Run combined coverage (SQLite + Postgres)
147
+ run: |
148
+ uv pip install pytest pytest-cov
149
+ just coverage
150
+
151
+ - name: Add coverage report to job summary
152
+ if: always()
153
+ run: |
154
+ {
155
+ echo "## Coverage"
156
+ echo ""
157
+ echo '```'
158
+ uv run coverage report -m
159
+ echo '```'
160
+ } >> "$GITHUB_STEP_SUMMARY"
161
+
162
+ - name: Upload HTML coverage report
163
+ if: always()
164
+ uses: actions/upload-artifact@v4
165
+ with:
166
+ name: htmlcov
167
+ path: htmlcov/
@@ -1,5 +1,65 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.17.4 (2026-01-05)
4
+
5
+ ### Bug Fixes
6
+
7
+ - **#503**: Preserve search index across server restarts
8
+ ([`26f7e98`](https://github.com/basicmachines-co/basic-memory/commit/26f7e98))
9
+ - Fixes critical bug where search index was wiped on every MCP server restart
10
+ - Bug was introduced in v0.16.3, affecting v0.16.3-v0.17.3
11
+ - **User action**: Run `basic-memory reset` once after updating to rebuild search index
12
+
13
+ ### Internal
14
+
15
+ - **#502**: Major architecture refactor with composition roots and typed API clients
16
+ ([`5947f04`](https://github.com/basicmachines-co/basic-memory/commit/5947f04))
17
+ - Add composition roots for API, MCP, and CLI entrypoints
18
+ - Split deps.py into feature-scoped modules (config, db, projects, repositories, services, importers)
19
+ - Add ProjectResolver for unified project selection
20
+ - Add SyncCoordinator for centralized sync/watch lifecycle
21
+ - Introduce typed API clients for MCP tools (KnowledgeClient, SearchClient, MemoryClient, etc.)
22
+
23
+ ## v0.17.3 (2026-01-03)
24
+
25
+ ### Features
26
+
27
+ - **#485**: Add stable external_id (UUID) to Project and Entity models
28
+ ([`a4000f6`](https://github.com/basicmachines-co/basic-memory/commit/a4000f6))
29
+ - Projects and entities now have immutable UUID identifiers
30
+ - API v2 endpoints use external_id for stable references
31
+ - Directory responses include external_id for entities
32
+
33
+ ### Bug Fixes
34
+
35
+ - **#501**: Update mcp dependency to support protocol version 2025-11-25
36
+ ([`c6baf58`](https://github.com/basicmachines-co/basic-memory/commit/c6baf58))
37
+ - Fixes "Unsupported protocol version" error when using Claude Code
38
+ - Bump mcp from >=1.2.0 to >=1.23.1
39
+
40
+ - **#499**: Fix route ordering for cloud deployments
41
+ ([`53c4c20`](https://github.com/basicmachines-co/basic-memory/commit/53c4c20))
42
+
43
+ - **#486**: Skip config file update for set_default_project in cloud mode
44
+ ([`fd732aa`](https://github.com/basicmachines-co/basic-memory/commit/fd732aa))
45
+
46
+ - **#484**: Make RelationResponse.from_id optional to handle null permalinks
47
+ ([`537e58a`](https://github.com/basicmachines-co/basic-memory/commit/537e58a))
48
+
49
+ - Use upsert to prevent IntegrityError during parallel search indexing
50
+ ([`4ce2198`](https://github.com/basicmachines-co/basic-memory/commit/4ce2198))
51
+
52
+ - Use relative file paths in importers for cloud storage compatibility
53
+ ([`8adf1f4`](https://github.com/basicmachines-co/basic-memory/commit/8adf1f4))
54
+
55
+ ### Internal
56
+
57
+ - Refactor importers to use FileService for cloud compatibility
58
+ ([`45ce181`](https://github.com/basicmachines-co/basic-memory/commit/45ce181))
59
+
60
+ - Strengthen integration test coverage, remove stdlib mocks
61
+ ([`b4486d2`](https://github.com/basicmachines-co/basic-memory/commit/b4486d2))
62
+
3
63
  ## v0.17.2 (2025-12-29)
4
64
 
5
65
  ### Bug Fixes
@@ -117,17 +117,38 @@ counter += 1 # track retries for backoff calculation
117
117
 
118
118
  ### Codebase Architecture
119
119
 
120
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for detailed architecture documentation.
121
+
122
+ **Directory Structure:**
120
123
  - `/alembic` - Alembic db migrations
121
- - `/api` - FastAPI implementation of REST endpoints
122
- - `/cli` - Typer command-line interface
124
+ - `/api` - FastAPI REST endpoints + `container.py` composition root
125
+ - `/cli` - Typer CLI + `container.py` composition root
126
+ - `/deps` - Feature-scoped FastAPI dependencies (config, db, projects, repositories, services, importers)
123
127
  - `/importers` - Import functionality for Claude, ChatGPT, and other sources
124
128
  - `/markdown` - Markdown parsing and processing
125
- - `/mcp` - Model Context Protocol server implementation
129
+ - `/mcp` - MCP server + `container.py` composition root + `clients/` typed API clients
126
130
  - `/models` - SQLAlchemy ORM models
127
131
  - `/repository` - Data access layer
128
132
  - `/schemas` - Pydantic models for validation
129
133
  - `/services` - Business logic layer
130
- - `/sync` - File synchronization services
134
+ - `/sync` - File synchronization services + `coordinator.py` for lifecycle management
135
+
136
+ **Composition Roots:**
137
+ Each entrypoint (API, MCP, CLI) has a composition root that:
138
+ - Reads `ConfigManager` (the only place that reads global config)
139
+ - Resolves runtime mode via `RuntimeMode` enum (TEST > CLOUD > LOCAL)
140
+ - Provides dependencies to downstream code explicitly
141
+
142
+ **Typed API Clients (MCP):**
143
+ MCP tools use typed clients in `mcp/clients/` to communicate with the API:
144
+ - `KnowledgeClient` - Entity CRUD operations
145
+ - `SearchClient` - Search operations
146
+ - `MemoryClient` - Context building
147
+ - `DirectoryClient` - Directory listing
148
+ - `ResourceClient` - Resource reading
149
+ - `ProjectClient` - Project management
150
+
151
+ Flow: MCP Tool → Typed Client → HTTP API → Router → Service → Repository
131
152
 
132
153
  ### Development Notes
133
154
 
@@ -146,6 +167,7 @@ counter += 1 # track retries for backoff calculation
146
167
  - CI runs SQLite and Postgres tests in parallel for faster feedback
147
168
  - Performance benchmarks are in `test-int/test_sync_performance_benchmark.py`
148
169
  - Use pytest markers: `@pytest.mark.benchmark` for benchmarks, `@pytest.mark.slow` for slow tests
170
+ - **Coverage must stay at 100%**: Write tests for new code. Only use `# pragma: no cover` when tests would require excessive mocking (e.g., TYPE_CHECKING blocks, error handlers that need failure injection, runtime-mode-dependent code paths)
149
171
 
150
172
  ### Async Client Pattern (Important!)
151
173
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.17.2
3
+ Version: 0.17.4
4
4
  Summary: Local-first knowledge management combining Zettelkasten with knowledge graphs
5
5
  Project-URL: Homepage, https://github.com/basicmachines-co/basic-memory
6
6
  Project-URL: Repository, https://github.com/basicmachines-co/basic-memory
@@ -19,7 +19,7 @@ Requires-Dist: fastmcp==2.12.3
19
19
  Requires-Dist: greenlet>=3.1.1
20
20
  Requires-Dist: loguru>=0.7.3
21
21
  Requires-Dist: markdown-it-py>=3.0.0
22
- Requires-Dist: mcp>=1.2.0
22
+ Requires-Dist: mcp>=1.23.1
23
23
  Requires-Dist: mdformat-frontmatter>=2.0.8
24
24
  Requires-Dist: mdformat-gfm>=0.3.7
25
25
  Requires-Dist: mdformat>=0.7.22
@@ -0,0 +1,412 @@
1
+ # Basic Memory Architecture
2
+
3
+ This document describes the architectural patterns and composition structure of Basic Memory.
4
+
5
+ ## Overview
6
+
7
+ Basic Memory is a local-first knowledge management system with three entrypoints:
8
+ - **API** - FastAPI REST server for HTTP access
9
+ - **MCP** - Model Context Protocol server for LLM integration
10
+ - **CLI** - Typer command-line interface
11
+
12
+ Each entrypoint uses a **composition root** pattern to manage configuration and dependencies.
13
+
14
+ ## Composition Roots
15
+
16
+ ### What is a Composition Root?
17
+
18
+ A composition root is the single place in an application where dependencies are wired together. In Basic Memory, each entrypoint has its own composition root that:
19
+
20
+ 1. Reads configuration from `ConfigManager`
21
+ 2. Resolves runtime mode (cloud/local/test)
22
+ 3. Creates and provides dependencies to downstream code
23
+
24
+ **Key principle**: Only composition roots read global configuration. All other modules receive configuration explicitly.
25
+
26
+ ### Container Structure
27
+
28
+ Each entrypoint has a container dataclass in its package:
29
+
30
+ ```
31
+ src/basic_memory/
32
+ ├── api/
33
+ │ └── container.py # ApiContainer
34
+ ├── mcp/
35
+ │ └── container.py # McpContainer
36
+ ├── cli/
37
+ │ └── container.py # CliContainer
38
+ └── runtime.py # RuntimeMode enum and resolver
39
+ ```
40
+
41
+ ### Container Pattern
42
+
43
+ All containers follow the same structure:
44
+
45
+ ```python
46
+ @dataclass
47
+ class Container:
48
+ config: BasicMemoryConfig
49
+ mode: RuntimeMode
50
+
51
+ @classmethod
52
+ def create(cls) -> "Container":
53
+ """Create container by reading ConfigManager."""
54
+ config = ConfigManager().config
55
+ mode = resolve_runtime_mode(
56
+ cloud_mode_enabled=config.cloud_mode_enabled,
57
+ is_test_env=config.is_test_env,
58
+ )
59
+ return cls(config=config, mode=mode)
60
+
61
+ @property
62
+ def some_computed_property(self) -> bool:
63
+ """Derived values based on config and mode."""
64
+ return self.mode.is_local and self.config.some_setting
65
+
66
+ # Module-level singleton
67
+ _container: Container | None = None
68
+
69
+ def get_container() -> Container:
70
+ if _container is None:
71
+ raise RuntimeError("Container not initialized")
72
+ return _container
73
+
74
+ def set_container(container: Container) -> None:
75
+ global _container
76
+ _container = container
77
+ ```
78
+
79
+ ### Runtime Mode Resolution
80
+
81
+ The `RuntimeMode` enum centralizes mode detection:
82
+
83
+ ```python
84
+ class RuntimeMode(Enum):
85
+ LOCAL = "local"
86
+ CLOUD = "cloud"
87
+ TEST = "test"
88
+
89
+ @property
90
+ def is_cloud(self) -> bool:
91
+ return self == RuntimeMode.CLOUD
92
+
93
+ @property
94
+ def is_local(self) -> bool:
95
+ return self == RuntimeMode.LOCAL
96
+
97
+ @property
98
+ def is_test(self) -> bool:
99
+ return self == RuntimeMode.TEST
100
+ ```
101
+
102
+ Resolution follows this precedence: **TEST > CLOUD > LOCAL**
103
+
104
+ ```python
105
+ def resolve_runtime_mode(cloud_mode_enabled: bool, is_test_env: bool) -> RuntimeMode:
106
+ if is_test_env:
107
+ return RuntimeMode.TEST
108
+ if cloud_mode_enabled:
109
+ return RuntimeMode.CLOUD
110
+ return RuntimeMode.LOCAL
111
+ ```
112
+
113
+ ## Dependencies Package
114
+
115
+ ### Structure
116
+
117
+ The `deps/` package provides FastAPI dependencies organized by feature:
118
+
119
+ ```
120
+ src/basic_memory/deps/
121
+ ├── __init__.py # Re-exports for backwards compatibility
122
+ ├── config.py # Configuration access
123
+ ├── db.py # Database/session management
124
+ ├── projects.py # Project resolution
125
+ ├── repositories.py # Data access layer
126
+ ├── services.py # Business logic layer
127
+ └── importers.py # Import functionality
128
+ ```
129
+
130
+ ### Usage in Routers
131
+
132
+ ```python
133
+ from basic_memory.deps.services import get_entity_service
134
+ from basic_memory.deps.projects import get_project_config
135
+
136
+ @router.get("/entities/{id}")
137
+ async def get_entity(
138
+ id: int,
139
+ entity_service: EntityService = Depends(get_entity_service),
140
+ project: ProjectConfig = Depends(get_project_config),
141
+ ):
142
+ return await entity_service.get(id)
143
+ ```
144
+
145
+ ### Backwards Compatibility
146
+
147
+ The old `deps.py` file still exists as a thin re-export shim:
148
+
149
+ ```python
150
+ # deps.py - backwards compatibility shim
151
+ from basic_memory.deps import *
152
+ ```
153
+
154
+ New code should import from specific submodules (`basic_memory.deps.services`) for clarity.
155
+
156
+ ## MCP Tools Architecture
157
+
158
+ ### Typed API Clients
159
+
160
+ MCP tools communicate with the API through typed clients that encapsulate HTTP paths and response validation:
161
+
162
+ ```
163
+ src/basic_memory/mcp/clients/
164
+ ├── __init__.py # Re-exports all clients
165
+ ├── base.py # BaseClient with common logic
166
+ ├── knowledge.py # KnowledgeClient - entity CRUD
167
+ ├── search.py # SearchClient - search operations
168
+ ├── memory.py # MemoryClient - context building
169
+ ├── directory.py # DirectoryClient - directory listing
170
+ ├── resource.py # ResourceClient - resource reading
171
+ └── project.py # ProjectClient - project management
172
+ ```
173
+
174
+ ### Client Pattern
175
+
176
+ Each client encapsulates API paths and validates responses:
177
+
178
+ ```python
179
+ class KnowledgeClient(BaseClient):
180
+ """Client for knowledge/entity operations."""
181
+
182
+ async def resolve_entity(self, identifier: str) -> int:
183
+ """Resolve identifier to entity ID."""
184
+ response = await call_get(
185
+ self.http_client,
186
+ f"{self._base_path}/resolve/{identifier}",
187
+ )
188
+ return int(response.text)
189
+
190
+ async def get_entity(self, entity_id: int) -> EntityResponse:
191
+ """Get entity by ID."""
192
+ response = await call_get(
193
+ self.http_client,
194
+ f"{self._base_path}/entities/{entity_id}",
195
+ )
196
+ return EntityResponse.model_validate(response.json())
197
+ ```
198
+
199
+ ### Tool → Client → API Flow
200
+
201
+ ```
202
+ MCP Tool (thin adapter)
203
+
204
+ Typed Client (encapsulates paths, validates responses)
205
+
206
+ HTTP API (FastAPI router)
207
+
208
+ Service Layer (business logic)
209
+
210
+ Repository Layer (data access)
211
+ ```
212
+
213
+ Example tool using typed client:
214
+
215
+ ```python
216
+ @mcp.tool()
217
+ async def search_notes(query: str, project: str | None = None) -> SearchResponse:
218
+ async with get_client() as client:
219
+ active_project = await get_active_project(client, project)
220
+
221
+ # Import client inside function to avoid circular imports
222
+ from basic_memory.mcp.clients import SearchClient
223
+
224
+ search_client = SearchClient(client, active_project.external_id)
225
+ return await search_client.search(query)
226
+ ```
227
+
228
+ ## Sync Coordination
229
+
230
+ ### SyncCoordinator
231
+
232
+ The `SyncCoordinator` centralizes sync/watch lifecycle management:
233
+
234
+ ```python
235
+ @dataclass
236
+ class SyncCoordinator:
237
+ """Coordinates file sync and watch operations."""
238
+
239
+ status: SyncStatus = SyncStatus.NOT_STARTED
240
+ sync_task: asyncio.Task | None = None
241
+ watch_service: WatchService | None = None
242
+
243
+ async def start(self, ...):
244
+ """Start sync and watch operations."""
245
+
246
+ async def stop(self):
247
+ """Stop all sync operations gracefully."""
248
+
249
+ def get_status_info(self) -> dict:
250
+ """Get current sync status for observability."""
251
+ ```
252
+
253
+ ### Status Enum
254
+
255
+ ```python
256
+ class SyncStatus(Enum):
257
+ NOT_STARTED = "not_started"
258
+ STARTING = "starting"
259
+ RUNNING = "running"
260
+ STOPPING = "stopping"
261
+ STOPPED = "stopped"
262
+ ERROR = "error"
263
+ ```
264
+
265
+ ## Project Resolution
266
+
267
+ ### ProjectResolver
268
+
269
+ Unified project selection across all entrypoints:
270
+
271
+ ```python
272
+ class ProjectResolver:
273
+ """Resolves which project to use based on context."""
274
+
275
+ def resolve(
276
+ self,
277
+ explicit_project: str | None = None,
278
+ ) -> ResolvedProject:
279
+ """Resolve project using three-tier hierarchy:
280
+ 1. Explicit project parameter
281
+ 2. Default project from config
282
+ 3. Single available project
283
+ """
284
+ ```
285
+
286
+ ### Resolution Modes
287
+
288
+ ```python
289
+ class ResolutionMode(Enum):
290
+ EXPLICIT = "explicit" # User specified project
291
+ DEFAULT = "default" # Using configured default
292
+ SINGLE_PROJECT = "single" # Only one project exists
293
+ FALLBACK = "fallback" # Using first available
294
+ ```
295
+
296
+ ## Testing Patterns
297
+
298
+ ### Container Testing
299
+
300
+ Each container has corresponding tests:
301
+
302
+ ```
303
+ tests/
304
+ ├── api/test_api_container.py
305
+ ├── mcp/test_mcp_container.py
306
+ └── cli/test_cli_container.py
307
+ ```
308
+
309
+ Tests verify:
310
+ - Container creation from config
311
+ - Runtime mode properties
312
+ - Container accessor functions (get/set)
313
+
314
+ ### Mocking Typed Clients
315
+
316
+ When testing MCP tools, mock at the client level:
317
+
318
+ ```python
319
+ def test_search_notes(monkeypatch):
320
+ import basic_memory.mcp.clients as clients_mod
321
+
322
+ class MockSearchClient:
323
+ async def search(self, query):
324
+ return SearchResponse(results=[...])
325
+
326
+ monkeypatch.setattr(clients_mod, "SearchClient", MockSearchClient)
327
+ ```
328
+
329
+ ## Design Principles
330
+
331
+ ### 1. Explicit Dependencies
332
+
333
+ Modules receive configuration explicitly rather than reading globals:
334
+
335
+ ```python
336
+ # Good - explicit injection
337
+ async def sync_files(config: BasicMemoryConfig):
338
+ ...
339
+
340
+ # Avoid - hidden global access
341
+ async def sync_files():
342
+ config = ConfigManager().config # Hidden coupling
343
+ ```
344
+
345
+ ### 2. Single Responsibility
346
+
347
+ Each layer has a clear responsibility:
348
+ - **Containers**: Wire dependencies
349
+ - **Clients**: Encapsulate HTTP communication
350
+ - **Services**: Business logic
351
+ - **Repositories**: Data access
352
+ - **Tools/Routers**: Thin adapters
353
+
354
+ ### 3. Deferred Imports
355
+
356
+ To avoid circular imports, typed clients are imported inside functions:
357
+
358
+ ```python
359
+ async def my_tool():
360
+ async with get_client() as client:
361
+ # Import here to avoid circular dependency
362
+ from basic_memory.mcp.clients import KnowledgeClient
363
+
364
+ knowledge_client = KnowledgeClient(client, project_id)
365
+ ```
366
+
367
+ ### 4. Backwards Compatibility
368
+
369
+ When refactoring, maintain backwards compatibility via shims:
370
+
371
+ ```python
372
+ # Old module becomes a shim
373
+ from basic_memory.new_location import *
374
+
375
+ # Docstring explains migration path
376
+ """
377
+ DEPRECATED: Import from basic_memory.new_location instead.
378
+ This shim will be removed in a future version.
379
+ """
380
+ ```
381
+
382
+ ## File Organization
383
+
384
+ ```
385
+ src/basic_memory/
386
+ ├── api/
387
+ │ ├── container.py # API composition root
388
+ │ ├── routers/ # FastAPI routers
389
+ │ └── ...
390
+ ├── mcp/
391
+ │ ├── container.py # MCP composition root
392
+ │ ├── clients/ # Typed API clients
393
+ │ ├── tools/ # MCP tool definitions
394
+ │ └── server.py # MCP server setup
395
+ ├── cli/
396
+ │ ├── container.py # CLI composition root
397
+ │ ├── app.py # Typer app
398
+ │ └── commands/ # CLI command groups
399
+ ├── deps/
400
+ │ ├── config.py # Config dependencies
401
+ │ ├── db.py # Database dependencies
402
+ │ ├── projects.py # Project dependencies
403
+ │ ├── repositories.py # Repository dependencies
404
+ │ ├── services.py # Service dependencies
405
+ │ └── importers.py # Importer dependencies
406
+ ├── sync/
407
+ │ ├── coordinator.py # SyncCoordinator
408
+ │ └── ...
409
+ ├── runtime.py # RuntimeMode resolution
410
+ ├── project_resolver.py # Unified project selection
411
+ └── config.py # Configuration management
412
+ ```
@@ -0,0 +1,30 @@
1
+ ## Coverage policy (practical 100%)
2
+
3
+ Basic Memory’s test suite intentionally mixes:
4
+ - unit tests (fast, deterministic)
5
+ - integration tests (real filesystem + real DB via `test-int/`)
6
+
7
+ To keep the default CI signal **stable and meaningful**, the default `pytest` coverage report targets **core library logic** and **excludes** a small set of modules that are either:
8
+ - highly environment-dependent (OS/DB tuning)
9
+ - inherently interactive (CLI)
10
+ - background-task orchestration (watchers/sync runners)
11
+ - external analytics
12
+
13
+ ### What’s excluded (and why)
14
+
15
+ Coverage excludes are configured in `pyproject.toml` under `[tool.coverage.report].omit`.
16
+
17
+ Current exclusions include:
18
+ - `src/basic_memory/cli/**`: interactive wrappers; behavior is validated via higher-level tests and smoke tests.
19
+ - `src/basic_memory/db.py`: platform/backend tuning paths (SQLite/Postgres/Windows), covered by integration tests and targeted runs.
20
+ - `src/basic_memory/services/initialization.py`: startup orchestration/background tasks; covered indirectly by app/MCP entrypoints.
21
+ - `src/basic_memory/sync/sync_service.py`: heavy filesystem↔DB integration; validated in integration suite (not enforced in unit coverage).
22
+ - `src/basic_memory/telemetry.py`: external analytics; exercised lightly but excluded from strict coverage gate.
23
+
24
+ ### Recommended additional runs
25
+
26
+ If you want extra confidence locally/CI:
27
+ - **Postgres backend**: run tests with `BASIC_MEMORY_TEST_POSTGRES=1`.
28
+ - **Strict backend-complete coverage**: run coverage on SQLite + Postgres and combine the results (recommended).
29
+
30
+