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.
- basic_memory-0.16.2/.claude/commands/release/release.md +169 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CHANGELOG.md +33 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/PKG-INFO +1 -1
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/__init__.py +1 -1
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_commands.py +30 -3
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py +18 -4
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/config.py +12 -9
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/cli/test_project_commands_integration.py +42 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_project_router.py +8 -8
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_service.py +24 -24
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_service_operations.py +10 -10
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_config.py +132 -21
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_rclone_commands.py +142 -14
- basic_memory-0.16.0/.claude/commands/release/release.md +0 -92
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/agents/python-developer.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/agents/system-architect.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/beta.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/changelog.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/release/release-check.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/spec.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.claude/commands/test-live.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.dockerignore +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/documentation.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/dependabot.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude-code-review.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude-issue-triage.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/claude.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/dev-release.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/docker.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/pr-title.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/release.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.github/workflows/test.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.gitignore +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/.python-version +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CITATION.cff +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CLA.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CLAUDE.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CODE_OF_CONDUCT.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/CONTRIBUTING.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/Dockerfile +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/LICENSE +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/README.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/SECURITY.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/docker-compose.yml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/Docker.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/ai-assistant-guide-extended.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/character-handling.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/docs/cloud-cli.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/justfile +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/llms-install.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/pyproject.toml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/smithery.yaml +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-1 Specification-Driven Development Process.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-10 Unified Deployment Workflow and Event Tracking.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-11 Basic Memory API Performance Optimization.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-12 OpenTelemetry Observability.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-13 CLI Authentication with Subscription Validation.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-14 Cloud Git Versioning & GitHub Backup.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-14- Cloud Git Versioning & GitHub Backup.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-15 Configuration Persistence via Tigris for Cloud Tenants.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-16 MCP Cloud Service Consolidation.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-17 Semantic Search with ChromaDB.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-18 AI Memory Management Tool.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-19 Sync Performance and Memory Optimization.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-2 Slash Commands Reference.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-20 Simplified Project-Scoped Rclone Sync.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-3 Agent Definitions.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-4 Notes Web UI Component Architecture.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-5 CLI Cloud Upload via WebDAV.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-6 Explicit Project Parameter Architecture.md +0 -0
- {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
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-8 TigrisFS Integration.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9 Multi-Project Bidirectional Sync Architecture.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9 Signed Header Tenant Information.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/specs/SPEC-9-1 Follow-Ups- Conflict, Sync, and Observability.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/alembic.ini +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/env.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/migrations.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/script.py.mako +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/3dae7c7b1564_initial_schema.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/502b60eaa905_remove_required_from_entity_permalink.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/5fe1ab1ccebe_add_projects_table.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/647e7a75e2cd_project_constraint_fix.py +0 -0
- {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
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/a1b2c3d4e5f6_fix_project_foreign_keys.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/b3c3938bacdb_relation_to_name_unique_index.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/alembic/versions/cc7172b46608_update_search_index_schema.py +0 -0
- {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
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/app.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/directory_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/importer_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/knowledge_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/management_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/memory_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/project_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/prompt_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/resource_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/search_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/routers/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/api/template_loader.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/app.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/auth.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/api_client.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/bisync_commands.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/cloud_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/core_commands.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_config.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/upload.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/upload_command.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/command_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/db.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_chatgpt.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_claude_conversations.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_claude_projects.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/import_memory_json.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/mcp.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/project.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/status.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/tool.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/main.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/db.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/deps.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/file_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/ignore_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/base.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/chatgpt_importer.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/claude_conversations_importer.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/claude_projects_importer.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/memory_json_importer.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/importers/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/entity_parser.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/markdown_processor.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/plugins.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/schemas.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/markdown/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/async_client.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/project_context.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/ai_assistant_guide.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/continue_conversation.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/recent_activity.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/prompts/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/resources/ai_assistant_guide.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/resources/project_info.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/server.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/build_context.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/canvas.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/chatgpt_tools.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/delete_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/edit_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/list_directory.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/move_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/project_management.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/read_content.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/read_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/recent_activity.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/view_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/mcp/tools/write_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/base.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/knowledge.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/project.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/models/search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/entity_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/observation_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/project_info_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/project_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/relation_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/repository/search_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/base.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/cloud.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/delete.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/directory.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/importer.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/memory.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/project_info.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/prompt.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/request.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/response.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/schemas/sync_report.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/context_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/directory_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/entity_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/exceptions.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/file_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/initialization.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/link_resolver.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/project_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/search_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/services/service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/background_sync.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/sync_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/sync/watch_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/templates/prompts/continue_conversation.hbs +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/templates/prompts/search.hbs +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/BENCHMARKS.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/cli/test_version_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/conftest.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_build_context_underscore.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_build_context_validation.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_chatgpt_tools_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_default_project_mode_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_delete_note_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_edit_note_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_list_directory_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_move_note_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_project_management_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_project_state_sync_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_read_content_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_read_note_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_search_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_single_project_mcp_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/mcp/test_write_note_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_db_wal_mode.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_disable_permalinks_integration.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/test_sync_performance_benchmark.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/Non-MarkdownFileSupport.pdf +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/Screenshot.png +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/conftest.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_async_client.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_continue_conversation_template.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_directory_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_importer_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_knowledge_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_management_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_memory_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_project_router_operations.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_prompt_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_relation_background_resolution.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_resource_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_search_router.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_search_template.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_template_loader.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/api/test_template_loader_helpers.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/conftest.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_cli_tools.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_cloud_authentication.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_ignore_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_chatgpt.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_claude_conversations.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_claude_projects.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_import_memory_json.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_project_add_with_local_path.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/cli/test_upload.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/conftest.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/db/test_issue_254_foreign_key_constraints.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/importers/test_importer_base.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/importers/test_importer_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/__init__.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_date_frontmatter_parsing.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_entity_parser.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_entity_parser_error_handling.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_markdown_plugins.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_markdown_processor.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_observation_edge_cases.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_parser_edge_cases.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_relation_edge_cases.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/markdown/test_task_detection.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/conftest.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_obsidian_yaml_formatting.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_permalink_collision_file_overwrite.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_prompts.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_resources.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_build_context.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_canvas.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_delete_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_edit_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_list_directory.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_move_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_read_content.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_read_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_recent_activity.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_resource.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_view_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/test_tool_write_note.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/mcp/tools/test_chatgpt_tools.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_repository_upsert.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_entity_upsert_issue_187.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_observation_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_project_info_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_project_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_relation_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_search_repository.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/repository/test_search_repository_edit_bug_fix.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_base_timeframe_minimum.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_serialization.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_url.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_memory_url_validation.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_schemas.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/schemas/test_search.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_context_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_directory_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_entity_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_entity_service_disable_permalinks.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_file_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_initialization.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_link_resolver.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_project_removal_bug.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/services/test_search_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_character_conflicts.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_service_incremental.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_sync_wikilink_issue.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_tmp_files.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service_edge_cases.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/sync/test_watch_service_reload.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_db_migration_deduplication.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_deps.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/test_production_cascade_delete.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_file_utils.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_frontmatter_obsidian_compatible.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_parse_tags.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_permalink_formatting.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_utf8_handling.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/tests/utils/test_validate_project_path.py +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/uv.lock +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v0.15.0-RELEASE-DOCS.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/README.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/api-performance.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/background-relations.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/basic-memory-home.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/bug-fixes.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/chatgpt-integration.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-authentication.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-bisync.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-mode-usage.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/cloud-mount.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/default-project-mode.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/env-file-removal.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/env-var-overrides.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/explicit-project-parameter.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/gitignore-integration.md +0 -0
- {basic_memory-0.16.0 → basic_memory-0.16.2}/v15-docs/project-root-env-var.md +0 -0
- {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.
|
|
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.
|
|
4
|
+
__version__ = "0.16.2"
|
|
5
5
|
|
|
6
6
|
# API version for FastAPI - independent of package version
|
|
7
7
|
__api_version__ = "v0"
|
{basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_commands.py
RENAMED
|
@@ -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
|
|
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}"
|
{basic_memory-0.16.0 → basic_memory-0.16.2}/src/basic_memory/cli/commands/cloud/rclone_installer.py
RENAMED
|
@@ -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
|
-
|
|
156
|
-
"Could not install rclone automatically
|
|
157
|
-
"
|
|
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"))
|
|
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
|
|
196
|
-
if
|
|
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
|
-
)
|
|
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
|
-
|
|
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
|
|
364
|
+
config.projects[name] = str(project_path)
|
|
362
365
|
self.save_config(config)
|
|
363
366
|
return ProjectConfig(name=name, home=project_path)
|
|
364
367
|
|
{basic_memory-0.16.0 → basic_memory-0.16.2}/test-int/cli/test_project_commands_integration.py
RENAMED
|
@@ -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 =
|
|
223
|
-
new_path =
|
|
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 =
|
|
80
|
+
test_project_path = test_root / "test-project"
|
|
81
81
|
|
|
82
82
|
# Make sure the test directory exists
|
|
83
|
-
|
|
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 =
|
|
176
|
+
test_project_path = test_root / "test-async-project"
|
|
177
177
|
|
|
178
178
|
# Make sure the test directory exists
|
|
179
|
-
|
|
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 =
|
|
573
|
-
new_path =
|
|
572
|
+
old_path = test_root / "old-location"
|
|
573
|
+
new_path = test_root / "new-location"
|
|
574
574
|
|
|
575
575
|
# Create old directory
|
|
576
|
-
|
|
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 =
|
|
628
|
-
new_path =
|
|
627
|
+
old_path = test_root / "old-location"
|
|
628
|
+
new_path = test_root / "new-location"
|
|
629
629
|
|
|
630
630
|
# Create directories
|
|
631
|
-
|
|
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
|