feat: add insert_before_section and insert_after_section edit operations#648
feat: add insert_before_section and insert_after_section edit operations#648phernandez merged 3 commits intomainfrom
Conversation
Add two new edit_note operations that use section headings as positional anchors to insert content without consuming the heading. This solves a real problem where LLMs using find_replace consistently eat section headings when trying to insert content near them. - insert_before_section: inserts content above a section heading - insert_after_section: inserts content below a section heading - Both require unique section headers (error on duplicates) - Both raise ValueError if section not found (unlike replace_section which appends) - Updated schema, service, and MCP tool layers consistently - Added unit tests, MCP tool tests, and schema validation tests Based on the work by @Brennall in PR #647, addressing issue #646. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
|
Claude finished @phernandez's task in 2m 25s —— View job PR Review: feat/insert-before-after-sectionTasks:
SummaryThis is a clean, well-motivated feature that addresses a real problem (LLMs eating section headings with Code Quality & Standards
Testing & Documentation
Basic Memory Architecture
Security & Performance
Compatibility
Issues Found1. Blank line asymmetry in
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b0c072f09
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| before = lines[: idx + 1] | ||
| after = lines[idx + 1 :] | ||
| insert_lines = new_content.rstrip("\n").split("\n") | ||
| return "\n".join(before + insert_lines + after) |
There was a problem hiding this comment.
Preserve paragraph boundaries after insert_after_section
When insert_after_section inserts plain text into a section that already starts with paragraph text, the current join logic places the old first line immediately after the inserted line with only a single newline, so Markdown treats them as one paragraph. This means the operation can unintentionally merge newly inserted text with existing section content instead of inserting a distinct block beneath the heading; adding explicit blank-line separation (as the before branch already does) avoids that formatting regression.
Useful? React with 👍 / 👎.
Add blank line between inserted content and existing section text so Markdown doesn't merge them into a single paragraph. Mirrors the blank-line separation already used in the insert_before_section path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
|
Claude finished @phernandez's task in 1m 38s —— View job PR Review: feat/insert-before-after-sectionTasks:
SummaryThe fix commit ( Five issues from the prior review remain open. Code Quality & Standards
Testing & Documentation
Basic Memory Architecture
Security & Performance
Compatibility
Fixed Since Last Review
Remaining Issues1. Stale validator docstringFile: @field_validator("section")
@classmethod
def validate_section_for_replace_section(cls, v, info):
"""Ensure section is provided for replace_section operation.""" # ← staleThe validator now also covers 2. Incomplete
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
|
Claude finished @phernandez's task in 1m 44s —— View job PR Review: feat/insert-before-after-sectionTasks:
What Changed in the Latest Commit
Code Quality & Standards
Testing & Documentation
Basic Memory Architecture
Security & Performance
Compatibility
Remaining Issues (unchanged from prior review)All five issues identified in the previous two reviews are still open. 1. Stale validator docstringFile: def validate_section_for_replace_section(cls, v, info):
"""Ensure section is provided for replace_section operation.""" # ← staleThe validator now covers 2. Incomplete
|
Summary
Adds two new
edit_noteoperations —insert_before_sectionandinsert_after_section— that use section headings as positional anchors to insert content without consuming the heading.insert_before_section: inserts content above a section headinginsert_after_section: inserts content below a section headingValueErrorif the section is not foundThis addresses a real problem where LLMs trained on
str_replacepatterns consistently eat section headings when usingfind_replaceto insert content near them.Based on the work by @Brennall in #647, addressing #646.
Changes
src/basic_memory/schemas/request.py— new operations in Literal type, updated section validatorsrc/basic_memory/services/entity_service.py—insert_relative_to_section()method + routing inapply_edit_operation()src/basic_memory/mcp/tools/edit_note.py— validation, response formatting, description updatestests/services/test_entity_service.py— 8 new unit teststests/mcp/test_tool_edit_note.py— 4 new MCP tool teststests/schemas/test_schemas.py— 3 new schema validation testsTest plan
pytest tests/services/test_entity_service.py -v -k "insert"— 8 unit tests passpytest tests/mcp/test_tool_edit_note.py -v -k "insert"— 4 MCP tool tests passpytest tests/schemas/test_schemas.py -v— all schema tests passpytest tests/mcp/test_tool_edit_note.py tests/schemas/test_schemas.py -v— all 79 tests pass🤖 Generated with Claude Code