basic-memory 0.16.0__tar.gz → 0.16.2__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 (362) hide show
  1. basic_memory-0.16.2/.claude/commands/release/release.md +169 -0
  2. {basic_memory-0.16.0 → basic_memory-0.16.2}/CHANGELOG.md +33 -0
  3. {basic_memory-0.16.0 → basic_memory-0.16.2}/PKG-INFO +1 -1
  4. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/__init__.py +1 -1
  5. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_commands.py +30 -3
  6. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +18 -4
  7. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/config.py +12 -9
  8. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/cli/test_project_commands_integration.py +42 -0
  9. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_project_router.py +8 -8
  10. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_service.py +24 -24
  11. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_service_operations.py +10 -10
  12. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_config.py +132 -21
  13. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_rclone_commands.py +142 -14
  14. basic_memory-0.16.0/.claude/commands/release/release.md +0 -92
  15. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/agents/python-developer.md +0 -0
  16. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/agents/system-architect.md +0 -0
  17. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/beta.md +0 -0
  18. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/changelog.md +0 -0
  19. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/release-check.md +0 -0
  20. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/spec.md +0 -0
  21. {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/test-live.md +0 -0
  22. {basic_memory-0.16.0 → basic_memory-0.16.2}/.dockerignore +0 -0
  23. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  24. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  25. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
  26. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  27. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/dependabot.yml +0 -0
  28. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude-code-review.yml +0 -0
  29. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude-issue-triage.yml +0 -0
  30. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude.yml +0 -0
  31. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/dev-release.yml +0 -0
  32. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/docker.yml +0 -0
  33. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/pr-title.yml +0 -0
  34. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/release.yml +0 -0
  35. {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/test.yml +0 -0
  36. {basic_memory-0.16.0 → basic_memory-0.16.2}/.gitignore +0 -0
  37. {basic_memory-0.16.0 → basic_memory-0.16.2}/.python-version +0 -0
  38. {basic_memory-0.16.0 → basic_memory-0.16.2}/CITATION.cff +0 -0
  39. {basic_memory-0.16.0 → basic_memory-0.16.2}/CLA.md +0 -0
  40. {basic_memory-0.16.0 → basic_memory-0.16.2}/CLAUDE.md +0 -0
  41. {basic_memory-0.16.0 → basic_memory-0.16.2}/CODE_OF_CONDUCT.md +0 -0
  42. {basic_memory-0.16.0 → basic_memory-0.16.2}/CONTRIBUTING.md +0 -0
  43. {basic_memory-0.16.0 → basic_memory-0.16.2}/Dockerfile +0 -0
  44. {basic_memory-0.16.0 → basic_memory-0.16.2}/LICENSE +0 -0
  45. {basic_memory-0.16.0 → basic_memory-0.16.2}/README.md +0 -0
  46. {basic_memory-0.16.0 → basic_memory-0.16.2}/SECURITY.md +0 -0
  47. {basic_memory-0.16.0 → basic_memory-0.16.2}/docker-compose.yml +0 -0
  48. {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/Docker.md +0 -0
  49. {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/ai-assistant-guide-extended.md +0 -0
  50. {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/character-handling.md +0 -0
  51. {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/cloud-cli.md +0 -0
  52. {basic_memory-0.16.0 → basic_memory-0.16.2}/justfile +0 -0
  53. {basic_memory-0.16.0 → basic_memory-0.16.2}/llms-install.md +0 -0
  54. {basic_memory-0.16.0 → basic_memory-0.16.2}/pyproject.toml +0 -0
  55. {basic_memory-0.16.0 → basic_memory-0.16.2}/smithery.yaml +0 -0
  56. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
  57. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
  58. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
  59. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
  60. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
  61. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
  62. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
  63. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
  64. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
  65. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
  66. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
  67. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
  68. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-2 Slash Commands Reference.md +0 -0
  69. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
  70. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-3 Agent Definitions.md +0 -0
  71. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
  72. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
  73. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
  74. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-7 POC to spike Tigris Turso for local access to cloud data.md +0 -0
  75. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-8 TigrisFS Integration.md +0 -0
  76. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
  77. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
  78. {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
  79. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/alembic.ini +0 -0
  80. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/env.py +0 -0
  81. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/migrations.py +0 -0
  82. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/script.py.mako +0 -0
  83. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
  84. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
  85. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
  86. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
  87. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/9d9c1cb7d8f5_add_mtime_and_size_columns_to_entity_.py +0 -0
  88. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
  89. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
  90. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
  91. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/e7e1f4367280_add_scan_watermark_tracking_to_project.py +0 -0
  92. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/__init__.py +0 -0
  93. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/app.py +0 -0
  94. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/__init__.py +0 -0
  95. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/directory_router.py +0 -0
  96. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/importer_router.py +0 -0
  97. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/knowledge_router.py +0 -0
  98. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/management_router.py +0 -0
  99. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/memory_router.py +0 -0
  100. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/project_router.py +0 -0
  101. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/prompt_router.py +0 -0
  102. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/resource_router.py +0 -0
  103. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/search_router.py +0 -0
  104. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/utils.py +0 -0
  105. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/template_loader.py +0 -0
  106. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/__init__.py +0 -0
  107. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/app.py +0 -0
  108. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/auth.py +0 -0
  109. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/__init__.py +0 -0
  110. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
  111. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
  112. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
  113. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
  114. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
  115. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
  116. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
  117. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
  118. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
  119. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/db.py +0 -0
  120. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
  121. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
  122. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
  123. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
  124. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/mcp.py +0 -0
  125. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/project.py +0 -0
  126. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/status.py +0 -0
  127. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/tool.py +0 -0
  128. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/main.py +0 -0
  129. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/db.py +0 -0
  130. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/deps.py +0 -0
  131. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/file_utils.py +0 -0
  132. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/ignore_utils.py +0 -0
  133. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/__init__.py +0 -0
  134. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/base.py +0 -0
  135. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
  136. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
  137. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
  138. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
  139. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/utils.py +0 -0
  140. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/__init__.py +0 -0
  141. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/entity_parser.py +0 -0
  142. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
  143. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/plugins.py +0 -0
  144. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/schemas.py +0 -0
  145. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/utils.py +0 -0
  146. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/__init__.py +0 -0
  147. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/async_client.py +0 -0
  148. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/project_context.py +0 -0
  149. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
  150. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
  151. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
  152. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
  153. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/search.py +0 -0
  154. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
  155. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
  156. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
  157. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/server.py +0 -0
  158. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
  159. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
  160. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/canvas.py +0 -0
  161. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
  162. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
  163. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
  164. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
  165. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
  166. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
  167. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
  168. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
  169. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
  170. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/search.py +0 -0
  171. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/utils.py +0 -0
  172. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
  173. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/write_note.py +0 -0
  174. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/__init__.py +0 -0
  175. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/base.py +0 -0
  176. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/knowledge.py +0 -0
  177. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/project.py +0 -0
  178. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/search.py +0 -0
  179. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/__init__.py +0 -0
  180. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/entity_repository.py +0 -0
  181. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/observation_repository.py +0 -0
  182. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/project_info_repository.py +0 -0
  183. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/project_repository.py +0 -0
  184. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/relation_repository.py +0 -0
  185. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/repository.py +0 -0
  186. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/search_repository.py +0 -0
  187. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/__init__.py +0 -0
  188. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/base.py +0 -0
  189. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/cloud.py +0 -0
  190. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/delete.py +0 -0
  191. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/directory.py +0 -0
  192. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/importer.py +0 -0
  193. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/memory.py +0 -0
  194. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/project_info.py +0 -0
  195. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/prompt.py +0 -0
  196. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/request.py +0 -0
  197. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/response.py +0 -0
  198. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/search.py +0 -0
  199. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/sync_report.py +0 -0
  200. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/__init__.py +0 -0
  201. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/context_service.py +0 -0
  202. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/directory_service.py +0 -0
  203. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/entity_service.py +0 -0
  204. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/exceptions.py +0 -0
  205. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/file_service.py +0 -0
  206. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/initialization.py +0 -0
  207. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/link_resolver.py +0 -0
  208. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/project_service.py +0 -0
  209. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/search_service.py +0 -0
  210. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/service.py +0 -0
  211. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/__init__.py +0 -0
  212. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/background_sync.py +0 -0
  213. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/sync_service.py +0 -0
  214. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/watch_service.py +0 -0
  215. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
  216. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
  217. {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/utils.py +0 -0
  218. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/BENCHMARKS.md +0 -0
  219. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/cli/test_version_integration.py +0 -0
  220. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/conftest.py +0 -0
  221. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_build_context_underscore.py +0 -0
  222. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_build_context_validation.py +0 -0
  223. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
  224. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
  225. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_delete_note_integration.py +0 -0
  226. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_edit_note_integration.py +0 -0
  227. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_list_directory_integration.py +0 -0
  228. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_move_note_integration.py +0 -0
  229. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_project_management_integration.py +0 -0
  230. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
  231. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_read_content_integration.py +0 -0
  232. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_read_note_integration.py +0 -0
  233. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_search_integration.py +0 -0
  234. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
  235. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_write_note_integration.py +0 -0
  236. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_db_wal_mode.py +0 -0
  237. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_disable_permalinks_integration.py +0 -0
  238. {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_sync_performance_benchmark.py +0 -0
  239. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
  240. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/Screenshot.png +0 -0
  241. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/__init__.py +0 -0
  242. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/conftest.py +0 -0
  243. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_async_client.py +0 -0
  244. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_continue_conversation_template.py +0 -0
  245. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_directory_router.py +0 -0
  246. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_importer_router.py +0 -0
  247. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_knowledge_router.py +0 -0
  248. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_management_router.py +0 -0
  249. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_memory_router.py +0 -0
  250. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_project_router_operations.py +0 -0
  251. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_prompt_router.py +0 -0
  252. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_relation_background_resolution.py +0 -0
  253. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_resource_router.py +0 -0
  254. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_search_router.py +0 -0
  255. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_search_template.py +0 -0
  256. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_template_loader.py +0 -0
  257. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_template_loader_helpers.py +0 -0
  258. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/conftest.py +0 -0
  259. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_cli_tools.py +0 -0
  260. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_cloud_authentication.py +0 -0
  261. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_ignore_utils.py +0 -0
  262. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_chatgpt.py +0 -0
  263. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_claude_conversations.py +0 -0
  264. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_claude_projects.py +0 -0
  265. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_memory_json.py +0 -0
  266. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_project_add_with_local_path.py +0 -0
  267. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_upload.py +0 -0
  268. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/conftest.py +0 -0
  269. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
  270. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/importers/test_importer_base.py +0 -0
  271. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/importers/test_importer_utils.py +0 -0
  272. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/__init__.py +0 -0
  273. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
  274. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_entity_parser.py +0 -0
  275. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_entity_parser_error_handling.py +0 -0
  276. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_markdown_plugins.py +0 -0
  277. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_markdown_processor.py +0 -0
  278. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_observation_edge_cases.py +0 -0
  279. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_parser_edge_cases.py +0 -0
  280. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_relation_edge_cases.py +0 -0
  281. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_task_detection.py +0 -0
  282. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/conftest.py +0 -0
  283. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
  284. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
  285. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_prompts.py +0 -0
  286. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_resources.py +0 -0
  287. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_build_context.py +0 -0
  288. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_canvas.py +0 -0
  289. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_delete_note.py +0 -0
  290. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_edit_note.py +0 -0
  291. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_list_directory.py +0 -0
  292. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_move_note.py +0 -0
  293. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_read_content.py +0 -0
  294. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_read_note.py +0 -0
  295. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_recent_activity.py +0 -0
  296. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_resource.py +0 -0
  297. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_search.py +0 -0
  298. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_utils.py +0 -0
  299. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_view_note.py +0 -0
  300. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_write_note.py +0 -0
  301. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
  302. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_repository.py +0 -0
  303. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_repository_upsert.py +0 -0
  304. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_upsert_issue_187.py +0 -0
  305. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_observation_repository.py +0 -0
  306. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_project_info_repository.py +0 -0
  307. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_project_repository.py +0 -0
  308. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_relation_repository.py +0 -0
  309. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_repository.py +0 -0
  310. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_search_repository.py +0 -0
  311. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
  312. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
  313. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_serialization.py +0 -0
  314. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_url.py +0 -0
  315. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_url_validation.py +0 -0
  316. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_schemas.py +0 -0
  317. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_search.py +0 -0
  318. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_context_service.py +0 -0
  319. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_directory_service.py +0 -0
  320. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_entity_service.py +0 -0
  321. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
  322. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_file_service.py +0 -0
  323. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_initialization.py +0 -0
  324. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_link_resolver.py +0 -0
  325. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_removal_bug.py +0 -0
  326. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_search_service.py +0 -0
  327. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_character_conflicts.py +0 -0
  328. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_service.py +0 -0
  329. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_service_incremental.py +0 -0
  330. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
  331. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_tmp_files.py +0 -0
  332. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service.py +0 -0
  333. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
  334. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service_reload.py +0 -0
  335. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_db_migration_deduplication.py +0 -0
  336. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_deps.py +0 -0
  337. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_production_cascade_delete.py +0 -0
  338. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_file_utils.py +0 -0
  339. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
  340. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_parse_tags.py +0 -0
  341. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_permalink_formatting.py +0 -0
  342. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_utf8_handling.py +0 -0
  343. {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_validate_project_path.py +0 -0
  344. {basic_memory-0.16.0 → basic_memory-0.16.2}/uv.lock +0 -0
  345. {basic_memory-0.16.0 → basic_memory-0.16.2}/v0.15.0-RELEASE-DOCS.md +0 -0
  346. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/README.md +0 -0
  347. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/api-performance.md +0 -0
  348. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/background-relations.md +0 -0
  349. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/basic-memory-home.md +0 -0
  350. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/bug-fixes.md +0 -0
  351. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/chatgpt-integration.md +0 -0
  352. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-authentication.md +0 -0
  353. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-bisync.md +0 -0
  354. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-mode-usage.md +0 -0
  355. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-mount.md +0 -0
  356. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/default-project-mode.md +0 -0
  357. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/env-file-removal.md +0 -0
  358. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/env-var-overrides.md +0 -0
  359. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/explicit-project-parameter.md +0 -0
  360. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/gitignore-integration.md +0 -0
  361. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/project-root-env-var.md +0 -0
  362. {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/sqlite-performance.md +0 -0
@@ -0,0 +1,169 @@
1
+ # /release - Create Stable Release
2
+
3
+ Create a stable release using the automated justfile target with comprehensive validation.
4
+
5
+ ## Usage
6
+ ```
7
+ /release <version>
8
+ ```
9
+
10
+ **Parameters:**
11
+ - `version` (required): Release version like `v0.13.2`
12
+
13
+ ## Implementation
14
+
15
+ You are an expert release manager for the Basic Memory project. When the user runs `/release`, execute the following steps:
16
+
17
+ ### Step 1: Pre-flight Validation
18
+
19
+ #### Version Check
20
+ 1. Check current version in `src/basic_memory/__init__.py`
21
+ 2. Verify new version format matches `v\d+\.\d+\.\d+` pattern
22
+ 3. Confirm version is higher than current version
23
+
24
+ #### Git Status
25
+ 1. Check current git status for uncommitted changes
26
+ 2. Verify we're on the `main` branch
27
+ 3. Confirm no existing tag with this version
28
+
29
+ #### Documentation Validation
30
+ 1. **Changelog Check**
31
+ - CHANGELOG.md contains entry for target version
32
+ - Entry includes all major features and fixes
33
+ - Breaking changes are documented
34
+
35
+ ### Step 2: Use Justfile Automation
36
+ Execute the automated release process:
37
+ ```bash
38
+ just release <version>
39
+ ```
40
+
41
+ The justfile target handles:
42
+ - ✅ Version format validation
43
+ - ✅ Git status and branch checks
44
+ - ✅ Quality checks (`just check` - lint, format, type-check, tests)
45
+ - ✅ Version update in `src/basic_memory/__init__.py`
46
+ - ✅ Automatic commit with proper message
47
+ - ✅ Tag creation and pushing to GitHub
48
+ - ✅ Release workflow trigger (automatic on tag push)
49
+
50
+ The GitHub Actions workflow (`.github/workflows/release.yml`) then:
51
+ - ✅ Builds the package using `uv build`
52
+ - ✅ Creates GitHub release with auto-generated notes
53
+ - ✅ Publishes to PyPI
54
+ - ✅ Updates Homebrew formula (stable releases only)
55
+
56
+ ### Step 3: Monitor Release Process
57
+ 1. Verify tag push triggered the workflow (should start automatically within seconds)
58
+ 2. Monitor workflow progress at: https://github.com/basicmachines-co/basic-memory/actions
59
+ 3. Watch for successful completion of both jobs:
60
+ - `release` - Builds package and publishes to PyPI
61
+ - `homebrew` - Updates Homebrew formula (stable releases only)
62
+ 4. Check for any workflow failures and investigate logs if needed
63
+
64
+ ### Step 4: Post-Release Validation
65
+
66
+ #### GitHub Release
67
+ 1. Verify GitHub release is created at: https://github.com/basicmachines-co/basic-memory/releases/tag/<version>
68
+ 2. Check that release notes are auto-generated from commits
69
+ 3. Validate release assets (`.whl` and `.tar.gz` files are attached)
70
+
71
+ #### PyPI Publication
72
+ 1. Verify package published at: https://pypi.org/project/basic-memory/<version>/
73
+ 2. Test installation: `uv tool install basic-memory`
74
+ 3. Verify installed version: `basic-memory --version`
75
+
76
+ #### Homebrew Formula (Stable Releases Only)
77
+ 1. Check formula update at: https://github.com/basicmachines-co/homebrew-basic-memory
78
+ 2. Verify formula version matches release
79
+ 3. Test Homebrew installation: `brew install basicmachines-co/basic-memory/basic-memory`
80
+
81
+ #### Website Updates
82
+
83
+ **1. basicmachines.co** (`/Users/drew/code/basicmachines.co`)
84
+ - **Goal**: Update version number displayed on the homepage
85
+ - **Location**: Search for "Basic Memory v0." in the codebase to find version displays
86
+ - **What to update**:
87
+ - Hero section heading that shows "Basic Memory v{VERSION}"
88
+ - "What's New in v{VERSION}" section heading
89
+ - Feature highlights array (look for array of features with title/description)
90
+ - **Process**:
91
+ 1. Pull latest from GitHub: `git pull origin main`
92
+ 2. Create release branch: `git checkout -b release/v{VERSION}`
93
+ 3. Search codebase for current version number (e.g., "v0.16.1")
94
+ 4. Update version numbers to new release version
95
+ 5. Update feature highlights with 3-5 key features from this release (extract from CHANGELOG.md)
96
+ 6. Commit changes: `git commit -m "chore: update to v{VERSION}"`
97
+ 7. Push branch: `git push origin release/v{VERSION}`
98
+ - **Deploy**: Follow deployment process for basicmachines.co
99
+
100
+ **2. docs.basicmemory.com** (`/Users/drew/code/docs.basicmemory.com`)
101
+ - **Goal**: Add new release notes section to the latest-releases page
102
+ - **File**: `src/pages/latest-releases.mdx`
103
+ - **What to do**:
104
+ 1. Pull latest from GitHub: `git pull origin main`
105
+ 2. Create release branch: `git checkout -b release/v{VERSION}`
106
+ 3. Read the existing file to understand the format and structure
107
+ 4. Read `/Users/drew/code/basic-memory/CHANGELOG.md` to get release content
108
+ 5. Add new release section **at the top** (after MDX imports, before other releases)
109
+ 6. Follow the existing pattern:
110
+ - Heading: `## [v{VERSION}](github-link) — YYYY-MM-DD`
111
+ - Focus statement if applicable
112
+ - `<Info>` block with highlights (3-5 key items)
113
+ - Sections for Features, Bug Fixes, Breaking Changes, etc.
114
+ - Link to full changelog at the end
115
+ - Separator `---` between releases
116
+ 7. Commit changes: `git commit -m "docs: add v{VERSION} release notes"`
117
+ 8. Push branch: `git push origin release/v{VERSION}`
118
+ - **Source content**: Extract and format sections from CHANGELOG.md for this version
119
+ - **Deploy**: Follow deployment process for docs.basicmemory.com
120
+
121
+ **4. Announce Release**
122
+ - Post to Discord community if significant changes
123
+ - Update social media if major release
124
+ - Notify users via appropriate channels
125
+
126
+ ## Pre-conditions Check
127
+ Before starting, verify:
128
+ - [ ] All beta testing is complete
129
+ - [ ] Critical bugs are fixed
130
+ - [ ] Breaking changes are documented
131
+ - [ ] CHANGELOG.md is updated (if needed)
132
+ - [ ] Version number follows semantic versioning
133
+
134
+ ## Error Handling
135
+ - If `just release` fails, examine the error output for specific issues
136
+ - If quality checks fail, fix issues and retry
137
+ - If changelog entry missing, update CHANGELOG.md and commit before retrying
138
+ - If GitHub Actions fail, check workflow logs for debugging
139
+
140
+ ## Success Output
141
+ ```
142
+ 🎉 Stable Release v0.13.2 Created Successfully!
143
+
144
+ 🏷️ Tag: v0.13.2
145
+ 📋 GitHub Release: https://github.com/basicmachines-co/basic-memory/releases/tag/v0.13.2
146
+ 📦 PyPI: https://pypi.org/project/basic-memory/0.13.2/
147
+ 🍺 Homebrew: https://github.com/basicmachines-co/homebrew-basic-memory
148
+ 🚀 GitHub Actions: Completed
149
+
150
+ Install with pip/uv:
151
+ uv tool install basic-memory
152
+
153
+ Install with Homebrew:
154
+ brew install basicmachines-co/basic-memory/basic-memory
155
+
156
+ Users can now upgrade:
157
+ uv tool upgrade basic-memory
158
+ brew upgrade basic-memory
159
+ ```
160
+
161
+ ## Context
162
+ - This creates production releases used by end users
163
+ - Must pass all quality gates before proceeding
164
+ - Uses the automated justfile target for consistency
165
+ - Version is automatically updated in `__init__.py`
166
+ - Triggers automated GitHub release with changelog
167
+ - Package is published to PyPI for `pip` and `uv` users
168
+ - Homebrew formula is automatically updated for stable releases
169
+ - Supports multiple installation methods (uv, pip, Homebrew)
@@ -1,5 +1,38 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v0.16.2 (2025-11-16)
4
+
5
+ ### Bug Fixes
6
+
7
+ - **#429**: Use platform-native path separators in config.json
8
+ ([`6517e98`](https://github.com/basicmachines-co/basic-memory/commit/6517e98))
9
+ - Fixes config.json path separator issues on Windows
10
+ - Uses os.path.join for platform-native path construction
11
+ - Ensures consistent path handling across platforms
12
+
13
+ - **#427**: Add rclone installation checks for Windows bisync commands
14
+ ([`1af0539`](https://github.com/basicmachines-co/basic-memory/commit/1af0539))
15
+ - Validates rclone installation before running bisync commands
16
+ - Provides clear error messages when rclone is not installed
17
+ - Improves user experience on Windows
18
+
19
+ - **#421**: Main project always recreated on project list command
20
+ ([`cad7019`](https://github.com/basicmachines-co/basic-memory/commit/cad7019))
21
+ - Fixes issue where main project was recreated unnecessarily
22
+ - Improves project list command reliability
23
+ - Reduces unnecessary file system operations
24
+
25
+ ## v0.16.1 (2025-11-11)
26
+
27
+ ### Bug Fixes
28
+
29
+ - **#422**: Handle Windows line endings in rclone bisync
30
+ ([`e9d0a94`](https://github.com/basicmachines-co/basic-memory/commit/e9d0a94))
31
+ - Added `--compare=modtime` flag to rclone bisync to ignore size differences from line ending conversions
32
+ - Fixes issue where LF→CRLF conversion on Windows was treated as file corruption
33
+ - Resolves "corrupted on transfer: sizes differ" errors during cloud sync on Windows
34
+ - Users will need to run `--resync` once after updating to establish new baseline
35
+
3
36
  ## v0.16.0 (2025-11-10)
4
37
 
5
38
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: basic-memory
3
- Version: 0.16.0
3
+ Version: 0.16.2
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
@@ -1,7 +1,7 @@
1
1
  """basic-memory - Local-first knowledge management combining Zettelkasten with knowledge graphs"""
2
2
 
3
3
  # Package version - updated by release automation
4
- __version__ = "0.16.0"
4
+ __version__ = "0.16.2"
5
5
 
6
6
  # API version for FastAPI - independent of package version
7
7
  __api_version__ = "v0"
@@ -16,6 +16,7 @@ from typing import Optional
16
16
 
17
17
  from rich.console import Console
18
18
 
19
+ from basic_memory.cli.commands.cloud.rclone_installer import is_rclone_installed
19
20
  from basic_memory.utils import normalize_project_path
20
21
 
21
22
  console = Console()
@@ -27,6 +28,21 @@ class RcloneError(Exception):
27
28
  pass
28
29
 
29
30
 
31
+ def check_rclone_installed() -> None:
32
+ """Check if rclone is installed and raise helpful error if not.
33
+
34
+ Raises:
35
+ RcloneError: If rclone is not installed with installation instructions
36
+ """
37
+ if not is_rclone_installed():
38
+ raise RcloneError(
39
+ "rclone is not installed.\n\n"
40
+ "Install rclone by running: bm cloud setup\n"
41
+ "Or install manually from: https://rclone.org/downloads/\n\n"
42
+ "Windows users: Ensure you have a package manager installed (winget, chocolatey, or scoop)"
43
+ )
44
+
45
+
30
46
  @dataclass
31
47
  class SyncProject:
32
48
  """Project configured for cloud sync.
@@ -124,8 +140,10 @@ def project_sync(
124
140
  True if sync succeeded, False otherwise
125
141
 
126
142
  Raises:
127
- RcloneError: If project has no local_sync_path configured
143
+ RcloneError: If project has no local_sync_path configured or rclone not installed
128
144
  """
145
+ check_rclone_installed()
146
+
129
147
  if not project.local_sync_path:
130
148
  raise RcloneError(f"Project {project.name} has no local_sync_path configured")
131
149
 
@@ -166,6 +184,7 @@ def project_bisync(
166
184
  Uses rclone bisync with balanced defaults:
167
185
  - conflict_resolve: newer (auto-resolve to most recent)
168
186
  - max_delete: 25 (safety limit)
187
+ - compare: modtime (ignore size differences from line ending conversions)
169
188
  - check_access: false (skip for performance)
170
189
 
171
190
  Args:
@@ -179,8 +198,10 @@ def project_bisync(
179
198
  True if bisync succeeded, False otherwise
180
199
 
181
200
  Raises:
182
- RcloneError: If project has no local_sync_path or needs --resync
201
+ RcloneError: If project has no local_sync_path, needs --resync, or rclone not installed
183
202
  """
203
+ check_rclone_installed()
204
+
184
205
  if not project.local_sync_path:
185
206
  raise RcloneError(f"Project {project.name} has no local_sync_path configured")
186
207
 
@@ -201,6 +222,7 @@ def project_bisync(
201
222
  "--resilient",
202
223
  "--conflict-resolve=newer",
203
224
  "--max-delete=25",
225
+ "--compare=modtime", # Ignore size differences from line ending conversions
204
226
  "--filter-from",
205
227
  str(filter_path),
206
228
  "--workdir",
@@ -247,8 +269,10 @@ def project_check(
247
269
  True if files match, False if differences found
248
270
 
249
271
  Raises:
250
- RcloneError: If project has no local_sync_path configured
272
+ RcloneError: If project has no local_sync_path configured or rclone not installed
251
273
  """
274
+ check_rclone_installed()
275
+
252
276
  if not project.local_sync_path:
253
277
  raise RcloneError(f"Project {project.name} has no local_sync_path configured")
254
278
 
@@ -289,7 +313,10 @@ def project_ls(
289
313
 
290
314
  Raises:
291
315
  subprocess.CalledProcessError: If rclone command fails
316
+ RcloneError: If rclone is not installed
292
317
  """
318
+ check_rclone_installed()
319
+
293
320
  remote_path = get_project_remote(project, bucket_name)
294
321
  if path:
295
322
  remote_path = f"{remote_path}/{path}"
@@ -151,11 +151,25 @@ def install_rclone_windows() -> None:
151
151
  except RcloneInstallError:
152
152
  console.print("[yellow]scoop installation failed[/yellow]")
153
153
 
154
- # No package manager available
155
- raise RcloneInstallError(
156
- "Could not install rclone automatically. Please install a package manager "
157
- "(winget, chocolatey, or scoop) or install rclone manually from https://rclone.org/downloads/"
154
+ # No package manager available - provide detailed instructions
155
+ error_msg = (
156
+ "Could not install rclone automatically.\n\n"
157
+ "Windows requires a package manager to install rclone. Options:\n\n"
158
+ "1. Install winget (recommended, built into Windows 11):\n"
159
+ " - Windows 11: Already installed\n"
160
+ " - Windows 10: Install 'App Installer' from Microsoft Store\n"
161
+ " - Then run: bm cloud setup\n\n"
162
+ "2. Install chocolatey:\n"
163
+ " - Visit: https://chocolatey.org/install\n"
164
+ " - Then run: bm cloud setup\n\n"
165
+ "3. Install scoop:\n"
166
+ " - Visit: https://scoop.sh\n"
167
+ " - Then run: bm cloud setup\n\n"
168
+ "4. Manual installation:\n"
169
+ " - Download from: https://rclone.org/downloads/\n"
170
+ " - Extract and add to PATH\n"
158
171
  )
172
+ raise RcloneInstallError(error_msg)
159
173
 
160
174
 
161
175
  def install_rclone(platform_override: Optional[str] = None) -> None:
@@ -63,8 +63,10 @@ class BasicMemoryConfig(BaseSettings):
63
63
 
64
64
  projects: Dict[str, str] = Field(
65
65
  default_factory=lambda: {
66
- "main": Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory")).as_posix()
67
- },
66
+ "main": str(Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory")))
67
+ }
68
+ if os.getenv("BASIC_MEMORY_HOME")
69
+ else {},
68
70
  description="Mapping of project names to their filesystem paths",
69
71
  )
70
72
  default_project: str = Field(
@@ -192,15 +194,16 @@ class BasicMemoryConfig(BaseSettings):
192
194
 
193
195
  def model_post_init(self, __context: Any) -> None:
194
196
  """Ensure configuration is valid after initialization."""
195
- # Ensure main project exists
196
- if "main" not in self.projects: # pragma: no cover
197
- self.projects["main"] = (
197
+ # Ensure at least one project exists; if none exist then create main
198
+ if not self.projects: # pragma: no cover
199
+ self.projects["main"] = str(
198
200
  Path(os.getenv("BASIC_MEMORY_HOME", Path.home() / "basic-memory"))
199
- ).as_posix()
201
+ )
200
202
 
201
- # Ensure default project is valid
203
+ # Ensure default project is valid (i.e. points to an existing project)
202
204
  if self.default_project not in self.projects: # pragma: no cover
203
- self.default_project = "main"
205
+ # Set default to first available project
206
+ self.default_project = next(iter(self.projects.keys()))
204
207
 
205
208
  @property
206
209
  def app_database_path(self) -> Path:
@@ -358,7 +361,7 @@ class ConfigManager:
358
361
 
359
362
  # Load config, modify it, and save it
360
363
  config = self.load_config()
361
- config.projects[name] = project_path.as_posix()
364
+ config.projects[name] = str(project_path)
362
365
  self.save_config(config)
363
366
  return ProjectConfig(name=name, home=project_path)
364
367
 
@@ -119,3 +119,45 @@ def test_project_set_default(app_config, config_manager):
119
119
  for line in lines:
120
120
  if "another-project" in line:
121
121
  assert "[X]" in line
122
+
123
+
124
+ def test_remove_main_project(app_config, config_manager):
125
+ """Test that removing main project then listing projects prevents main from reappearing (issue #397)."""
126
+ runner = CliRunner()
127
+
128
+ # Create separate temp dirs for each project
129
+ with (
130
+ tempfile.TemporaryDirectory() as main_dir,
131
+ tempfile.TemporaryDirectory() as new_default_dir,
132
+ ):
133
+ main_path = Path(main_dir)
134
+ new_default_path = Path(new_default_dir)
135
+
136
+ # Ensure main exists
137
+ result = runner.invoke(app, ["project", "list"])
138
+ if "main" not in result.stdout:
139
+ result = runner.invoke(app, ["project", "add", "main", str(main_path)])
140
+ print(result.stdout)
141
+ assert result.exit_code == 0
142
+
143
+ # Confirm main is present
144
+ result = runner.invoke(app, ["project", "list"])
145
+ assert "main" in result.stdout
146
+
147
+ # Add a second project
148
+ result = runner.invoke(app, ["project", "add", "new_default", str(new_default_path)])
149
+ assert result.exit_code == 0
150
+
151
+ # Set new_default as default (if needed)
152
+ result = runner.invoke(app, ["project", "default", "new_default"])
153
+ assert result.exit_code == 0
154
+
155
+ # Remove main
156
+ result = runner.invoke(app, ["project", "remove", "main"])
157
+ assert result.exit_code == 0
158
+
159
+ # Confirm only new_default exists and main does not
160
+ result = runner.invoke(app, ["project", "list"])
161
+ assert result.exit_code == 0
162
+ assert "main" not in result.stdout
163
+ assert "new_default" in result.stdout
@@ -219,20 +219,20 @@ async def test_update_project_path_endpoint(test_config, client, project_service
219
219
  test_project_name = "test-update-project"
220
220
  with tempfile.TemporaryDirectory() as temp_dir:
221
221
  test_root = Path(temp_dir)
222
- old_path = (test_root / "old-location").as_posix()
223
- new_path = (test_root / "new-location").as_posix()
222
+ old_path = test_root / "old-location"
223
+ new_path = test_root / "new-location"
224
224
 
225
- await project_service.add_project(test_project_name, old_path)
225
+ await project_service.add_project(test_project_name, str(old_path))
226
226
 
227
227
  try:
228
228
  # Verify initial state
229
229
  project = await project_service.get_project(test_project_name)
230
230
  assert project is not None
231
- assert project.path == old_path
231
+ assert Path(project.path) == old_path
232
232
 
233
233
  # Update the project path
234
234
  response = await client.patch(
235
- f"{project_url}/project/{test_project_name}", json={"path": new_path}
235
+ f"{project_url}/project/{test_project_name}", json={"path": str(new_path)}
236
236
  )
237
237
 
238
238
  # Verify response
@@ -248,16 +248,16 @@ async def test_update_project_path_endpoint(test_config, client, project_service
248
248
 
249
249
  # Check old project data
250
250
  assert data["old_project"]["name"] == test_project_name
251
- assert data["old_project"]["path"] == old_path
251
+ assert Path(data["old_project"]["path"]) == old_path
252
252
 
253
253
  # Check new project data
254
254
  assert data["new_project"]["name"] == test_project_name
255
- assert data["new_project"]["path"] == new_path
255
+ assert Path(data["new_project"]["path"]) == new_path
256
256
 
257
257
  # Verify project was actually updated in database
258
258
  updated_project = await project_service.get_project(test_project_name)
259
259
  assert updated_project is not None
260
- assert updated_project.path == new_path
260
+ assert Path(updated_project.path) == new_path
261
261
 
262
262
  finally:
263
263
  # Clean up
@@ -77,18 +77,18 @@ async def test_project_operations_sync_methods(
77
77
  test_project_name = f"test-project-{os.urandom(4).hex()}"
78
78
  with tempfile.TemporaryDirectory() as temp_dir:
79
79
  test_root = Path(temp_dir)
80
- test_project_path = (test_root / "test-project").as_posix()
80
+ test_project_path = test_root / "test-project"
81
81
 
82
82
  # Make sure the test directory exists
83
- os.makedirs(test_project_path, exist_ok=True)
83
+ test_project_path.mkdir(parents=True, exist_ok=True)
84
84
 
85
85
  try:
86
86
  # Test adding a project (using ConfigManager directly)
87
- config_manager.add_project(test_project_name, test_project_path)
87
+ config_manager.add_project(test_project_name, str(test_project_path))
88
88
 
89
89
  # Verify it was added
90
90
  assert test_project_name in project_service.projects
91
- assert project_service.projects[test_project_name] == test_project_path
91
+ assert Path(project_service.projects[test_project_name]) == test_project_path
92
92
 
93
93
  # Test setting as default
94
94
  original_default = project_service.default_project
@@ -173,24 +173,24 @@ async def test_add_project_async(project_service: ProjectService):
173
173
  test_project_name = f"test-async-project-{os.urandom(4).hex()}"
174
174
  with tempfile.TemporaryDirectory() as temp_dir:
175
175
  test_root = Path(temp_dir)
176
- test_project_path = (test_root / "test-async-project").as_posix()
176
+ test_project_path = test_root / "test-async-project"
177
177
 
178
178
  # Make sure the test directory exists
179
- os.makedirs(test_project_path, exist_ok=True)
179
+ test_project_path.mkdir(parents=True, exist_ok=True)
180
180
 
181
181
  try:
182
182
  # Test adding a project
183
- await project_service.add_project(test_project_name, test_project_path)
183
+ await project_service.add_project(test_project_name, str(test_project_path))
184
184
 
185
185
  # Verify it was added to config
186
186
  assert test_project_name in project_service.projects
187
- assert project_service.projects[test_project_name] == test_project_path
187
+ assert Path(project_service.projects[test_project_name]) == test_project_path
188
188
 
189
189
  # Verify it was added to the database
190
190
  project = await project_service.repository.get_by_name(test_project_name)
191
191
  assert project is not None
192
192
  assert project.name == test_project_name
193
- assert project.path == test_project_path
193
+ assert Path(project.path) == test_project_path
194
194
 
195
195
  finally:
196
196
  # Clean up
@@ -569,34 +569,34 @@ async def test_move_project(project_service: ProjectService):
569
569
  test_project_name = f"test-move-project-{os.urandom(4).hex()}"
570
570
  with tempfile.TemporaryDirectory() as temp_dir:
571
571
  test_root = Path(temp_dir)
572
- old_path = (test_root / "old-location").as_posix()
573
- new_path = (test_root / "new-location").as_posix()
572
+ old_path = test_root / "old-location"
573
+ new_path = test_root / "new-location"
574
574
 
575
575
  # Create old directory
576
- os.makedirs(old_path, exist_ok=True)
576
+ old_path.mkdir(parents=True, exist_ok=True)
577
577
 
578
578
  try:
579
579
  # Add project with initial path
580
- await project_service.add_project(test_project_name, old_path)
580
+ await project_service.add_project(test_project_name, str(old_path))
581
581
 
582
582
  # Verify initial state
583
583
  assert test_project_name in project_service.projects
584
- assert project_service.projects[test_project_name] == old_path
584
+ assert Path(project_service.projects[test_project_name]) == old_path
585
585
 
586
586
  project = await project_service.repository.get_by_name(test_project_name)
587
587
  assert project is not None
588
- assert project.path == old_path
588
+ assert Path(project.path) == old_path
589
589
 
590
590
  # Move project to new location
591
- await project_service.move_project(test_project_name, new_path)
591
+ await project_service.move_project(test_project_name, str(new_path))
592
592
 
593
593
  # Verify config was updated
594
- assert project_service.projects[test_project_name] == new_path
594
+ assert Path(project_service.projects[test_project_name]) == new_path
595
595
 
596
596
  # Verify database was updated
597
597
  updated_project = await project_service.repository.get_by_name(test_project_name)
598
598
  assert updated_project is not None
599
- assert updated_project.path == new_path
599
+ assert Path(updated_project.path) == new_path
600
600
 
601
601
  # Verify new directory was created
602
602
  assert os.path.exists(new_path)
@@ -624,17 +624,17 @@ async def test_move_project_db_mismatch(project_service: ProjectService):
624
624
  test_project_name = f"test-move-mismatch-{os.urandom(4).hex()}"
625
625
  with tempfile.TemporaryDirectory() as temp_dir:
626
626
  test_root = Path(temp_dir)
627
- old_path = (test_root / "old-location").as_posix()
628
- new_path = (test_root / "new-location").as_posix()
627
+ old_path = test_root / "old-location"
628
+ new_path = test_root / "new-location"
629
629
 
630
630
  # Create directories
631
- os.makedirs(old_path, exist_ok=True)
631
+ old_path.mkdir(parents=True, exist_ok=True)
632
632
 
633
633
  config_manager = project_service.config_manager
634
634
 
635
635
  try:
636
636
  # Add project to config only (not to database)
637
- config_manager.add_project(test_project_name, old_path)
637
+ config_manager.add_project(test_project_name, str(old_path))
638
638
 
639
639
  # Verify it's in config but not in database
640
640
  assert test_project_name in project_service.projects
@@ -643,10 +643,10 @@ async def test_move_project_db_mismatch(project_service: ProjectService):
643
643
 
644
644
  # Try to move project - should fail and restore config
645
645
  with pytest.raises(ValueError, match="not found in database"):
646
- await project_service.move_project(test_project_name, new_path)
646
+ await project_service.move_project(test_project_name, str(new_path))
647
647
 
648
648
  # Verify config was restored to original path
649
- assert project_service.projects[test_project_name] == old_path
649
+ assert Path(project_service.projects[test_project_name]) == old_path
650
650
 
651
651
  finally:
652
652
  # Clean up