Skip to content

Commit d3b6c85

Browse files
phernandezclaude
andcommitted
docs: add v0.13.8 changelog entry
Documents recent fixes and features including: - Docker container support with volume mounting - #151: Reset command project configuration fix - #148: MCP/CLI project state consistency fix - FastMCP compatibility improvements - Comprehensive integration testing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent af44941 commit d3b6c85

5 files changed

Lines changed: 107 additions & 47 deletions

File tree

CHANGELOG.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,64 @@
11
# CHANGELOG
22

3+
## v0.13.8 (2025-06-20)
4+
5+
### Features
6+
7+
- **Docker Container Support** - Complete Docker integration with volume mounting for Obsidian directories
8+
([`3269a2f`](https://github.com/basicmachines-co/basic-memory/commit/3269a2f33a7595f6d9e5207924062e2542f46759))
9+
- Docker Compose configuration for easy deployment
10+
- Volume mounting for persistent data and Obsidian integration
11+
- Comprehensive Docker documentation and setup guides
12+
- Streamlined container-based workflow
13+
14+
### Bug Fixes
15+
16+
- **#151**: Fix reset command project configuration persistence issue
17+
([`af44941`](https://github.com/basicmachines-co/basic-memory/commit/af44941d5aa57b5ad7fcc6af4ed700f49bdb6d4d))
18+
- Reset command now properly clears project configuration from `~/.basic-memory/config.json`
19+
- Eliminates issue where projects would be recreated after database reset
20+
- Ensures clean slate when resetting Basic Memory installation
21+
22+
- **#148**: Resolve project state inconsistency between MCP and CLI
23+
([`35e4f73`](https://github.com/basicmachines-co/basic-memory/commit/35e4f73ae8a65501da4d48258ed702f957184c92))
24+
- Fix "Project not found" errors when switching default projects
25+
- MCP session now automatically refreshes when project configuration changes
26+
- Eliminates need to restart MCP server after project operations
27+
- Ensures consistent project state across CLI and MCP interfaces
28+
29+
- **FastMCP Compatibility** - Resolve deprecation warnings for FastMCP integration
30+
([`7be001c`](https://github.com/basicmachines-co/basic-memory/commit/7be001ca6834b3344bb6160cbe537b36bcbaa579))
31+
- Update FastMCP usage patterns to eliminate deprecation warnings
32+
- Improve future compatibility with FastMCP library updates
33+
- Clean up entity repository and service layer code
34+
35+
### Technical Improvements
36+
37+
- **Comprehensive Integration Testing** - New test suites for critical user workflows
38+
- Full integration tests for database reset functionality
39+
- End-to-end project state synchronization testing
40+
- Real MCP client-server communication validation
41+
- Direct config file validation without complex mocking
42+
43+
- **Code Quality** - Enhanced error handling and validation
44+
- Improved project state management across system components
45+
- Better session refresh patterns for configuration changes
46+
- Streamlined Docker setup with reduced image size
47+
48+
### Documentation
49+
50+
- **Docker Integration Guide** - Complete documentation for container deployment
51+
- Step-by-step Docker Compose setup instructions
52+
- Volume mounting configuration for Obsidian workflows
53+
- Container-based development environment setup
54+
55+
## v0.13.7 (2025-06-19)
56+
57+
### Bug Fixes
58+
59+
- **Homebrew Integration** - Automatic Homebrew formula updates
60+
- **Documentation** - Add git sign-off reminder to development guide
61+
362
## v0.13.6 (2025-06-18)
463

564
### Bug Fixes

src/basic_memory/mcp/project_session.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,15 @@ def reset_to_default(self) -> None: # pragma: no cover
6666

6767
def refresh_from_config(self) -> None:
6868
"""Refresh session state from current configuration.
69-
69+
7070
This method reloads the default project from config and reinitializes
7171
the session. This should be called when the default project is changed
7272
via CLI or API to ensure MCP session stays in sync.
7373
"""
7474
# Reload config to get latest default project
7575
current_config = config_manager.load_config()
7676
new_default = current_config.default_project
77-
77+
7878
# Reinitialize with new default
7979
self.initialize(new_default)
8080
logger.info(f"Refreshed project session from config, new default: {new_default}")

src/basic_memory/mcp/prompts/sync_status.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,6 @@
1212
)
1313
async def sync_status_prompt() -> str:
1414
"""Get sync status with AI assistant guidance.
15-
16-
This prompt provides detailed sync status information along with
17-
recommendations for how AI assistants should handle different sync states.
18-
1915
Returns:
2016
Formatted sync status with AI assistant guidance
2117
"""

src/basic_memory/services/project_service.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,13 @@ async def set_default_project(self, name: str) -> None:
153153
logger.error(f"Project '{name}' exists in config but not in database")
154154

155155
logger.info(f"Project '{name}' set as default in configuration and database")
156-
156+
157157
# Refresh MCP session to pick up the new default project
158158
try:
159159
from basic_memory.mcp.project_session import session
160+
160161
session.refresh_from_config()
161-
except ImportError:
162+
except ImportError: # pragma: no cover
162163
# MCP components might not be available in all contexts (e.g., CLI-only usage)
163164
logger.debug("MCP session not available, skipping session refresh")
164165

@@ -281,10 +282,11 @@ async def synchronize_projects(self) -> None: # pragma: no cover
281282
await self.repository.set_as_default(project.id)
282283

283284
logger.info("Project synchronization complete")
284-
285+
285286
# Refresh MCP session to ensure it's in sync with current config
286287
try:
287288
from basic_memory.mcp.project_session import session
289+
288290
session.refresh_from_config()
289291
except ImportError:
290292
# MCP components might not be available in all contexts

test-int/cli/test_reset_integration.py

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
intact in ~/.basic-memory/config.json.
66
77
The test verifies that the reset command now:
8-
1. Removes the SQLite database
8+
1. Removes the SQLite database
99
2. Resets project configuration to default state (main project only)
1010
3. Recreates empty database
1111
"""
@@ -20,136 +20,139 @@
2020
@pytest.mark.asyncio
2121
async def test_reset_config_file_behavior(config_manager):
2222
"""Test that reset command properly updates the config.json file."""
23-
23+
2424
# Step 1: Set up initial state with multiple projects in config
2525
original_projects = {
2626
"project1": "/path/to/project1",
27-
"project2": "/path/to/project2",
28-
"user-project": "/home/user/documents"
27+
"project2": "/path/to/project2",
28+
"user-project": "/home/user/documents",
2929
}
3030
config_manager.config.projects = original_projects.copy()
3131
config_manager.config.default_project = "user-project"
32-
32+
3333
# Step 2: Save the config to a temporary file to simulate the real config file
3434
with tempfile.TemporaryDirectory() as temp_dir:
3535
temp_config_file = Path(temp_dir) / "config.json"
3636
config_manager.config_file = temp_config_file
3737
config_manager.save_config(config_manager.config)
38-
38+
3939
# Step 3: Verify the config file contains the multiple projects
4040
config_json = json.loads(temp_config_file.read_text())
4141
assert len(config_json["projects"]) == 3
4242
assert config_json["default_project"] == "user-project"
4343
assert "project1" in config_json["projects"]
4444
assert "project2" in config_json["projects"]
4545
assert "user-project" in config_json["projects"]
46-
46+
4747
# Step 4: Simulate the reset command's configuration reset behavior
4848
# This is the exact fix for issue #151
4949
with patch("pathlib.Path.home") as mock_home:
5050
mock_home.return_value = Path("/home/testuser")
51-
51+
5252
# Apply the reset logic from the reset command
5353
config_manager.config.projects = {"main": str(Path.home() / "basic-memory")}
5454
config_manager.config.default_project = "main"
5555
config_manager.save_config(config_manager.config)
56-
56+
5757
# Step 5: Read the config file and verify it was properly reset
5858
updated_config_json = json.loads(temp_config_file.read_text())
59-
59+
6060
# Should now only have the main project
6161
assert len(updated_config_json["projects"]) == 1
6262
assert "main" in updated_config_json["projects"]
6363
assert updated_config_json["projects"]["main"] == "/home/testuser/basic-memory"
6464
assert updated_config_json["default_project"] == "main"
65-
65+
6666
# All original projects should be gone from the file
6767
assert "project1" not in updated_config_json["projects"]
6868
assert "project2" not in updated_config_json["projects"]
6969
assert "user-project" not in updated_config_json["projects"]
70-
70+
7171
# This validates that issue #151 is fixed:
7272
# Before the fix, these projects would persist in config.json after reset
7373
# After the fix, only the default "main" project remains
7474

7575

76-
@pytest.mark.asyncio
76+
@pytest.mark.asyncio
7777
async def test_reset_command_source_code_validation():
7878
"""Validate that the reset command source contains the required fix."""
7979
# This test ensures the fix for issue #151 is present in the source code
80-
reset_source_path = Path(__file__).parent.parent.parent / "src" / "basic_memory" / "cli" / "commands" / "db.py"
80+
reset_source_path = (
81+
Path(__file__).parent.parent.parent / "src" / "basic_memory" / "cli" / "commands" / "db.py"
82+
)
8183
reset_source = reset_source_path.read_text()
82-
84+
8385
# Verify the key components of the fix are present
8486
required_lines = [
85-
'# Reset project configuration',
87+
"# Reset project configuration",
8688
'config_manager.config.projects = {"main": str(Path.home() / "basic-memory")}',
8789
'config_manager.config.default_project = "main"',
88-
'config_manager.save_config(config_manager.config)',
89-
'logger.info("Project configuration reset to default")'
90+
"config_manager.save_config(config_manager.config)",
91+
'logger.info("Project configuration reset to default")',
9092
]
91-
93+
9294
for line in required_lines:
9395
assert line in reset_source, f"Required fix line not found: {line}"
94-
96+
9597
# Verify the fix is in the correct location (after database deletion, before recreation)
96-
lines = reset_source.split('\n')
97-
98+
lines = reset_source.split("\n")
99+
98100
# Find key markers
99101
db_deletion_line = None
100102
config_reset_line = None
101103
db_recreation_line = None
102-
104+
103105
for i, line in enumerate(lines):
104-
if 'db_path.unlink()' in line:
106+
if "db_path.unlink()" in line:
105107
db_deletion_line = i
106-
elif 'config_manager.config.projects = {' in line:
108+
elif "config_manager.config.projects = {" in line:
107109
config_reset_line = i
108-
elif 'asyncio.run(db.run_migrations' in line:
110+
elif "asyncio.run(db.run_migrations" in line:
109111
db_recreation_line = i
110-
112+
111113
# Verify the order is correct
112114
assert db_deletion_line is not None, "Database deletion code not found"
113-
assert config_reset_line is not None, "Config reset code not found"
115+
assert config_reset_line is not None, "Config reset code not found"
114116
assert db_recreation_line is not None, "Database recreation code not found"
115-
117+
116118
# Config reset should be after db deletion and before db recreation
117-
assert db_deletion_line < config_reset_line < db_recreation_line, \
119+
assert db_deletion_line < config_reset_line < db_recreation_line, (
118120
"Config reset is not in the correct order in the reset command"
121+
)
119122

120123

121124
@pytest.mark.asyncio
122125
async def test_config_reset_behavior_simulation(config_manager):
123126
"""Test the specific configuration reset behavior that fixes issue #151."""
124-
127+
125128
# Step 1: Set up the problem state (multiple projects in config)
126129
original_projects = {
127130
"project1": "/path/to/project1",
128131
"project2": "/path/to/project2",
129-
"user-project": "/home/user/documents"
132+
"user-project": "/home/user/documents",
130133
}
131134
config_manager.config.projects = original_projects.copy()
132135
config_manager.config.default_project = "user-project"
133-
136+
134137
# Verify the problem state
135138
assert len(config_manager.config.projects) == 3
136139
assert config_manager.config.default_project == "user-project"
137-
140+
138141
# Step 2: Apply the reset fix (simulate what reset command does)
139142
with patch("pathlib.Path.home") as mock_home:
140143
mock_home.return_value = Path("/home/testuser")
141-
144+
142145
# This is the exact code from the reset command that fixes issue #151
143146
config_manager.config.projects = {"main": str(Path.home() / "basic-memory")}
144147
config_manager.config.default_project = "main"
145148
# Note: We don't call save_config in test to avoid file operations
146-
149+
147150
# Step 3: Verify the fix worked
148151
assert len(config_manager.config.projects) == 1
149152
assert "main" in config_manager.config.projects
150153
assert config_manager.config.projects["main"] == "/home/testuser/basic-memory"
151154
assert config_manager.config.default_project == "main"
152-
155+
153156
# Step 4: Verify original projects are gone
154157
for project_name in original_projects:
155-
assert project_name not in config_manager.config.projects
158+
assert project_name not in config_manager.config.projects

0 commit comments

Comments
 (0)