Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/basic_memory/mcp/tools/move_note.py
Original file line number Diff line number Diff line change
Expand Up @@ -941,9 +941,9 @@ async def _ensure_resolved_entity_id() -> str:
moved within the same project. To move content between projects:

```
read_note("{identifier}")
read_note("{result.file_path}")
write_note("Title", "content", "folder", project="target-project")
delete_note("{identifier}", project="{active_project.name}")
delete_note("{result.file_path}", project="{active_project.name}")
```
""").strip()

Expand Down
51 changes: 51 additions & 0 deletions test-int/bughunt_fixes/test_move_note_edge_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,54 @@ async def test_move_into_nested_projects_folder_not_flagged(mcp_server, app, tes
"Legit nested 'projects' folder wrongly flagged as cross-project move"
)
assert result["moved"] is True, result.get("error")


@pytest.mark.asyncio
async def test_move_outcome_mismatch_guidance_uses_actual_landing_path(
mcp_server, app, test_project, monkeypatch
):
"""The text guidance should point agents at the actual post-move path.

The real move service stores the requested destination verbatim today, so the
mismatch backstop is exercised by returning a divergent file_path after the real
move completes.
"""
async with Client(mcp_server) as client:
await client.call_tool(
"write_note",
{
"project": test_project.name,
"title": "Outcome Guidance Note",
"directory": "source",
"content": "# Outcome Guidance Note\n\nbody",
"output_format": "json",
},
)

from basic_memory.mcp.clients import KnowledgeClient

real_move_entity = KnowledgeClient.move_entity
actual_landing_path = "unexpected/outcome-guidance-note.md"

async def diverging_move_entity(self, entity_id, destination_path):
result = await real_move_entity(self, entity_id, destination_path)
return result.model_copy(update={"file_path": actual_landing_path})

monkeypatch.setattr(KnowledgeClient, "move_entity", diverging_move_entity)

move = await client.call_tool(
"move_note",
{
"project": test_project.name,
"identifier": "source/outcome-guidance-note",
"destination_path": "target/outcome-guidance-note.md",
},
)

guidance = move.content[0].text
stale_identifier = "source/outcome-guidance-note"
assert "Unexpected Result Location" in guidance
assert f'read_note("{actual_landing_path}")' in guidance
assert f'delete_note("{actual_landing_path}", project="{test_project.name}")' in guidance
assert f'read_note("{stale_identifier}")' not in guidance
assert f'delete_note("{stale_identifier}", project="{test_project.name}")' not in guidance
Loading