460 lines
14 KiB
Markdown
460 lines
14 KiB
Markdown
# Update Memory - Update Existing Note
|
|
|
|
Update an existing memory note with new information, using patch operations and conflict detection.
|
|
|
|
## Usage
|
|
|
|
```
|
|
/update-memory [title]
|
|
```
|
|
|
|
**Arguments:**
|
|
- `title` - The title of the existing memory note to update (required)
|
|
|
|
**Examples:**
|
|
```
|
|
/update-memory Git Worktrees
|
|
/update-memory 2025-11-18 - Working Memory Implementation
|
|
/update-memory React Patterns
|
|
```
|
|
|
|
## Implementation
|
|
|
|
When this command is invoked:
|
|
|
|
### 1. Parse and Validate Title
|
|
|
|
1. Parse the title by trimming whitespace from the command input
|
|
2. Validate that the title is not empty
|
|
- If title is empty, return error message: "Title is required. Usage: /update-memory [title]"
|
|
|
|
### 2. Detect Project Context
|
|
|
|
1. Attempt to detect the current project from the git repository:
|
|
- Run `git rev-parse --show-toplevel` to find the git repository root
|
|
- Extract the project name from the repository directory name
|
|
2. If not in a git repository:
|
|
- Fall back to using the current working directory name
|
|
- If that fails, use 'default' as the project name
|
|
3. Store the detected project name for locating the note
|
|
|
|
### 3. Search for Note
|
|
|
|
1. Try to find the note by checking multiple possible locations in order:
|
|
- Current project entities: `claude/projects/{currentProject}/entities/{title}.md`
|
|
- Current project sessions: `claude/projects/{currentProject}/sessions/{title}.md`
|
|
- Global entities: `claude/global/entities/{title}.md`
|
|
- Global topics: `claude/global/topics/{title}.md`
|
|
|
|
2. For each possible path:
|
|
- Attempt to read the note using MCP `read_note`
|
|
- If successful, store the path and note content, then stop searching
|
|
- If FileNotFoundError, continue to next path
|
|
- If other error, propagate it
|
|
|
|
3. If not found in standard locations, use search as fallback:
|
|
- Invoke MCP `search_notes` with query=title and path_filter='claude/**'
|
|
- Find exact title match in results (case-insensitive comparison)
|
|
- If exact match found, load the note using MCP `read_note`
|
|
|
|
4. If still not found after all attempts:
|
|
- Return error message listing all searched locations
|
|
- Suggest using /remember to create the note
|
|
- Provide example command
|
|
|
|
### 4. Load Note and Check Timestamps
|
|
|
|
1. Store the loaded timestamp from frontmatter for conflict detection later
|
|
- Save note.frontmatter.updated as the loaded timestamp
|
|
|
|
2. Update claude_last_accessed in frontmatter to current date (YYYY-MM-DD)
|
|
|
|
3. Display the current note content to the user:
|
|
- Show wikilink title, type, project, last updated date, and path
|
|
- Display full current content
|
|
- Add separator line
|
|
- Prompt: "What would you like to update? I'll apply patch operations to preserve existing content."
|
|
|
|
### 5. Collect User Updates
|
|
|
|
This is a conversational step where the user describes what they want to update.
|
|
|
|
1. User provides their update request in natural language
|
|
- Example: "Add a new decision about using trap handlers for cleanup"
|
|
|
|
2. Parse the user's intent to identify the appropriate patch operation type:
|
|
- Append to section: Add new entry to an existing section (e.g., "## Recent Changes")
|
|
- Add new section: Create a completely new section (e.g., "## Troubleshooting")
|
|
- Update frontmatter: Modify frontmatter fields (e.g., add a tag)
|
|
- Insert in list: Add item to an existing list (e.g., "## Related Entities")
|
|
|
|
3. Confirm with the user what will be done
|
|
- Example: "I'll add this to the Key Decisions section."
|
|
|
|
### 6. Check for Conflicts (Before Writing)
|
|
|
|
Use the conflict detection logic defined in the managing-working-memory skill:
|
|
|
|
1. Before applying the patch, reload the note using MCP `read_note` to get the current state
|
|
|
|
2. Compare timestamps to detect conflicts:
|
|
- Get the current timestamp from the reloaded note's frontmatter.updated
|
|
- Compare with the loaded timestamp saved in step 4
|
|
- If current timestamp > loaded timestamp: CONFLICT DETECTED (human edited since Claude loaded)
|
|
- If timestamps match: No conflict, safe to update
|
|
|
|
3. If conflict detected:
|
|
- Trigger conflict resolution flow (see managing-working-memory skill for detailed flow)
|
|
- Present both changes to user and offer resolution options
|
|
|
|
4. If no conflict:
|
|
- Proceed to apply patch operation in next step
|
|
|
|
### 7. Apply Patch Operation
|
|
|
|
Use the patch operation patterns defined in the managing-working-memory skill. Apply the identified patch operation type:
|
|
|
|
**For append_to_section:**
|
|
- Locate the specified section in the note content
|
|
- Append the new content to the end of that section
|
|
- Preserve all existing content in the section
|
|
|
|
**For add_new_section:**
|
|
- Create a new markdown section with the specified title
|
|
- Add the section content
|
|
- Insert at appropriate location in the note structure
|
|
|
|
**For update_frontmatter:**
|
|
- Modify the specified frontmatter field(s)
|
|
- Common operations: adding tags, updating status, etc.
|
|
|
|
**For insert_in_list:**
|
|
- Locate the specified list within a section
|
|
- Add the new list item
|
|
- Maintain proper markdown list formatting
|
|
|
|
After applying content changes:
|
|
|
|
1. Update frontmatter timestamps:
|
|
- Set updated to current date (YYYY-MM-DD)
|
|
- Set claude_last_accessed to current date (YYYY-MM-DD)
|
|
|
|
2. If adding tags, merge new tags with existing tags (remove duplicates)
|
|
|
|
### 8. Write Updated Note
|
|
|
|
1. Invoke MCP `update_note` with:
|
|
- vault: `~/.claude-memory`
|
|
- path: The note path
|
|
- content: The updated content
|
|
- frontmatter: The updated frontmatter
|
|
|
|
2. Handle the response:
|
|
|
|
**If successful:**
|
|
- Return success message including:
|
|
- Confirmation with wikilink
|
|
- Description of applied changes
|
|
- Updated timestamp
|
|
- Path
|
|
- Note that Obsidian has been updated
|
|
|
|
**If MCPUnavailableError:**
|
|
- Return graceful degradation message explaining:
|
|
- MCP server is unavailable
|
|
- Steps to restore: ensure Obsidian is running, check plugin installation, verify config
|
|
- Reference to docs/setup-guide.md
|
|
- Offer to save pending update to a local file
|
|
|
|
**If other error:**
|
|
- Return error message with details
|
|
|
|
## Conflict Detection and Resolution
|
|
|
|
All conflict detection and resolution flows are defined in the managing-working-memory skill. The /update-memory command uses these patterns:
|
|
|
|
### Case 1: Clean Update (No Conflict)
|
|
|
|
Timeline:
|
|
- T1: Claude loads note (updated = "2025-11-17")
|
|
- T2: User discusses updates with Claude
|
|
- T3: Claude applies patch (updated still "2025-11-17")
|
|
- Result: No conflict, proceed with update
|
|
|
|
See managing-working-memory skill for timestamp comparison logic.
|
|
|
|
**Example Output:**
|
|
```
|
|
Updated: [[Git Worktrees]]
|
|
|
|
Applied changes:
|
|
- Added new entry to "Recent Changes"
|
|
- Appended decision about trap handlers to "Key Decisions"
|
|
- Updated tags: [entity, git, worktrees, error-handling]
|
|
|
|
Updated: 2025-11-18
|
|
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
|
|
|
|
The note has been updated in Obsidian.
|
|
```
|
|
|
|
### Case 2: Human Edit Conflict
|
|
|
|
Timeline:
|
|
- T1: Claude loads note (updated = "2025-11-17")
|
|
- T2: Human edits note in Obsidian (updated = "2025-11-18")
|
|
- T3: Claude attempts patch (detects conflict)
|
|
- Result: Conflict detected, show diff and offer resolution options
|
|
|
|
See managing-working-memory skill for conflict resolution flow and user options.
|
|
|
|
**Example Output:**
|
|
```
|
|
I want to update [[Git Worktrees]] but you've edited it since I loaded it.
|
|
|
|
Your changes (at 2025-11-18):
|
|
+ Added new section "## Performance Considerations"
|
|
+ Updated "Overview" with additional context
|
|
~ Modified frontmatter tags: added #optimization
|
|
|
|
My pending changes:
|
|
- Add new entry to "Recent Changes"
|
|
- Append decision about trap handlers to "Key Decisions"
|
|
|
|
Options:
|
|
1. Show me both diffs and I'll merge manually
|
|
2. Abort your update (keep my changes only)
|
|
3. Create new section "## Claude's Updates (conflicted)" with your changes
|
|
4. Let's discuss and resolve together
|
|
|
|
What should I do?
|
|
```
|
|
|
|
### Case 3: Major Rewrite Needed
|
|
|
|
When Claude's understanding contradicts existing note fundamentally, use the major rewrite pattern from managing-working-memory skill to present options without overwriting user knowledge.
|
|
|
|
**Example Output:**
|
|
```
|
|
My understanding of [[Git Worktrees]] changed significantly.
|
|
|
|
Current note says:
|
|
"Git worktrees are primarily for parallel feature development and should be short-lived."
|
|
|
|
But I now think:
|
|
"Git worktrees can be long-lived for maintaining multiple release branches simultaneously."
|
|
|
|
Options:
|
|
1. Create new entity note with alternative understanding
|
|
2. Update existing note (I'll show you the full diff first)
|
|
3. Let's discuss the contradiction - maybe both are valid
|
|
|
|
What should I do?
|
|
```
|
|
|
|
## Patch Operation Types
|
|
|
|
All patch operations are defined in the managing-working-memory skill. The /update-memory command uses these standard patterns:
|
|
|
|
### 1. Append to Section
|
|
|
|
Add new content at the end of an existing section. Example: Adding to "## Recent Changes" section.
|
|
|
|
See managing-working-memory skill for appendToSection pattern.
|
|
|
|
### 2. Add New Section
|
|
|
|
Create a new section in the note. Example: Adding "## Performance Considerations" section.
|
|
|
|
See managing-working-memory skill for addSection pattern.
|
|
|
|
### 3. Update Frontmatter
|
|
|
|
Modify frontmatter fields such as tags or status.
|
|
|
|
Examples:
|
|
- Adding a tag: Append to tags array
|
|
- Changing status: Set status field to new value
|
|
|
|
See managing-working-memory skill for frontmatter update pattern.
|
|
|
|
### 4. Insert in List
|
|
|
|
Add item to an existing list like "## Related Entities" or "## References".
|
|
|
|
See managing-working-memory skill for insertInList pattern.
|
|
|
|
## Error Handling
|
|
|
|
### Note Not Found
|
|
|
|
**Input:** `/update-memory Nonexistent Entity`
|
|
|
|
**Output:**
|
|
```
|
|
Error: Memory note [[Nonexistent Entity]] not found.
|
|
|
|
Searched:
|
|
- Project entities: claude/projects/tabula-scripta/entities/
|
|
- Project sessions: claude/projects/tabula-scripta/sessions/
|
|
- Global entities: claude/global/entities/
|
|
- Global topics: claude/global/topics/
|
|
|
|
Would you like to create it with /remember?
|
|
|
|
Example: /remember entity Nonexistent Entity
|
|
```
|
|
|
|
### MCP Unavailable
|
|
|
|
**Input:** `/update-memory Git Worktrees` (when MCP server is down)
|
|
|
|
**Output:**
|
|
```
|
|
Obsidian MCP server is unavailable. Cannot update memory note.
|
|
|
|
To restore memory features:
|
|
1. Ensure Obsidian is running
|
|
2. Check obsidian-mcp-plugin is installed in ~/.claude-memory/
|
|
3. Verify Claude Code config includes MCP server
|
|
|
|
See docs/setup-guide.md for troubleshooting.
|
|
|
|
Would you like me to save the pending update to a local file?
|
|
```
|
|
|
|
### Missing Title
|
|
|
|
**Input:** `/update-memory`
|
|
|
|
**Output:**
|
|
```
|
|
Error: Title is required.
|
|
|
|
Usage: /update-memory [title]
|
|
|
|
Examples:
|
|
/update-memory Git Worktrees
|
|
/update-memory 2025-11-18 - Working Memory Implementation
|
|
/update-memory React Patterns
|
|
```
|
|
|
|
## Success Output (Clean Update)
|
|
|
|
**Input:** `/update-memory Git Worktrees`
|
|
|
|
**Conversation:**
|
|
```
|
|
User: /update-memory Git Worktrees
|
|
|
|
Claude: Loaded: [[Git Worktrees]]
|
|
Type: entity
|
|
Project: tabula-scripta
|
|
Last updated: 2025-11-17
|
|
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
|
|
|
|
Current content:
|
|
[... full note content ...]
|
|
|
|
---
|
|
|
|
What would you like to update? I'll apply patch operations to preserve existing content.
|
|
|
|
User: Add a decision about using trap handlers for cleanup
|
|
|
|
Claude: I'll add this to the Key Decisions section.
|
|
|
|
[Claude applies patch]
|
|
|
|
Updated: [[Git Worktrees]]
|
|
|
|
Applied changes:
|
|
- Added new entry to "Key Decisions"
|
|
### Trap Handlers for Cleanup
|
|
Date: 2025-11-18
|
|
Rationale: Ensures worktree cleanup even if subagent crashes
|
|
Alternatives Considered: Manual cleanup (error-prone), atexit hooks (unreliable)
|
|
Impact: Improves reliability of parallel execution
|
|
|
|
Updated: 2025-11-18
|
|
Path: claude/projects/tabula-scripta/entities/Git Worktrees.md
|
|
|
|
The note has been updated in Obsidian.
|
|
```
|
|
|
|
## Timestamp Tracking
|
|
|
|
### Frontmatter Fields
|
|
|
|
```yaml
|
|
---
|
|
created: 2025-11-17 # Never changes, original creation
|
|
updated: 2025-11-18 # Modified every save (human or Claude)
|
|
claude_last_accessed: 2025-11-18 # When Claude loaded into context
|
|
---
|
|
```
|
|
|
|
### Conflict Detection Logic
|
|
|
|
See the managing-working-memory skill for the complete timestamp comparison logic. The basic flow is:
|
|
|
|
1. **When loading:** Store the updated timestamp and set claude_last_accessed
|
|
2. **When updating:** Reload the note and compare timestamps
|
|
3. **If current timestamp > loaded timestamp:** Conflict detected
|
|
4. **If timestamps match:** Safe to update
|
|
|
|
## Graceful Degradation (MCP Unavailable)
|
|
|
|
When MCP server is unavailable:
|
|
|
|
1. **Detect failure** - Catch `MCPUnavailableError`
|
|
2. **Offer alternatives:**
|
|
- Save pending update to local markdown file
|
|
- Export as diff patch for manual application
|
|
- Continue conversation without update
|
|
3. **Guide troubleshooting:**
|
|
- Link to `docs/setup-guide.md`
|
|
- Check Obsidian is running
|
|
- Verify plugin installation
|
|
|
|
## Interactive Update Flow
|
|
|
|
The `/update-memory` command is conversational:
|
|
|
|
1. **Load note** - Show current content to user
|
|
2. **Collect intent** - User describes what to update
|
|
3. **Confirm operation** - Claude describes patch operation
|
|
4. **Check conflict** - Reload note to detect edits
|
|
5. **Apply or resolve** - Update cleanly or trigger conflict resolution
|
|
6. **Confirm success** - Show what changed
|
|
|
|
This ensures transparency and prevents data loss.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] Loads existing note via MCP read_note
|
|
- [ ] Checks timestamps for conflict detection (updated vs loaded)
|
|
- [ ] Detects conflicts when human edited since load
|
|
- [ ] Shows diff when conflict detected
|
|
- [ ] Applies patch operations (append, add section, update frontmatter)
|
|
- [ ] Preserves existing content (no full rewrites)
|
|
- [ ] Updates frontmatter timestamps (updated, claude_last_accessed)
|
|
- [ ] Handles MCP unavailable gracefully
|
|
- [ ] Offers to create note if not found
|
|
- [ ] Searches multiple locations (project entities, sessions, global)
|
|
- [ ] Shows clear success message with changes applied
|
|
|
|
## Integration with managing-working-memory Skill
|
|
|
|
This command provides the manual interface for memory updates. The `managing-working-memory` skill uses the same update logic for:
|
|
- Automatic updates after code review
|
|
- Updates after debugging sessions
|
|
- Periodic checkpoint updates
|
|
- Session end compaction
|
|
|
|
**Relationship:**
|
|
- `/update-memory` - Manual, user-initiated updates
|
|
- `managing-working-memory` - Automatic, skill-driven updates
|
|
- Both use identical conflict detection and patch operations
|
|
- Both track timestamps for data integrity
|