Skip to content

write-note: add explicit --type arg; lock in content-frontmatter note_type with an integration test #875

@phernandez

Description

@phernandez

Background

The Claude Code memory-bridge plugin (#865) writes typed notes — type: session checkpoints, type: schema/decision seeds — through basic-memory tool write-note, relying on Basic Memory deriving note_type from the leading content frontmatter (services/entity_service.py:322-323 on create, 607-608 on update).

A Codex review on #865 (review 4397262976) flagged this as broken (P1) — believing the type is stripped and note_type defaults to note. It's a false positive (verified by reproduction + the code path; the cited markdown/utils.py:108-116 runs after the derivation). But settling it required a manual repro, and it exposed two real gaps worth fixing:

  1. The behavior is implicit and fragile. The CLI write-note has no way to set note_type directly, so the plugin hooks depend on frontmatter derivation rather than stating intent.
  2. It's untested. Nothing asserts the round-trip, which is exactly why the reviewer and the implementation disagreed.

Part 1 — write-note should accept an explicit --type (note_type)

The MCP write_note tool has a note_type param (src/basic_memory/mcp/tools/write_note.py:42), but the CLI basic-memory tool write-note exposes only --title/--folder/--content/--tags/--project/--project-id. Add the missing flag.

  • Add --type (note_type) to the tool write-note CLI command, passed through to write_note(note_type=...).
  • Define precedence when both an explicit --type and a content-frontmatter type are present (suggest: explicit --type wins; content frontmatter remains the fallback when --type is omitted, preserving today's behavior).
  • Update the plugin's PreCompact hook to pass --type session explicitly instead of relying on embedded frontmatter (plugins/claude-code/hooks/pre-compact.sh).
  • Update the setup skill's schema-seed step and /basic-memory:share to pass note_type explicitly via the MCP write_note(note_type=...) (they currently rely on content frontmatter). plugins/claude-code/skills/{setup,share}/.

Part 2 — Integration test: note_type round-trips

Lock in the behavior the review questioned so a future entity_service change can't silently break the memory bridge (and so reviewers/bots have ground truth).

  • Write a note whose content frontmatter is type: session (no explicit note_type) → assert the persisted entity has note_type == "session" and search_notes(metadata_filters={"type": "session"}) returns it.
  • Same for type: schema → assert it's found by the note_type == "schema" path and resolves via schema_validate.
  • After Part 1: assert an explicit --type sets note_type, and cover the precedence rule above.
  • (Optional) plugin smoke: a PreCompact-style checkpoint is found by the SessionStart --type session query.

Why both

Part 1 turns an implicit dependency into a first-class, explicit option for callers. Part 2 turns the behavior into a guaranteed contract. Together they would have pre-empted the entire #865 review back-and-forth.

Refs: #865, codex review 4397262976.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions