Skip to content

bug(doctor): upgrade doctor blocked by legacy empty-content observation mutation with no local-only repair path (cloud not configured)Β #690

Description

@eduardoalvara2

πŸ“‹ Pre-flight Checks

  • I have searched existing issues and this is not a duplicate
  • I understand this issue needs status:approved before a PR can be opened

πŸ“ Bug Description

Two linked defects observed after upgrading engram 1.15.10 β†’ 1.20.0 on a machine where cloud is not configured:

  1. Capture-side: mem_session_summary (MCP, running v1.15.10 at the time) persisted a session_summary observation (#2447) with empty content, even though the MCP call included the full markdown body. mem_get_observation returned only metadata (title/session/scope/timestamps) β€” no content. This extends the empty-content class from fix(sync): empty prompt content accepted at capture poisons cloud push for all projects; repair cannot fix prompt entitiesΒ #686 (prompt entities) to observation entities.
  2. Repair-side: after upgrading to 1.20.0, engram doctor reports blocked on sync_mutation_required_fields for the queued upsert of that observation (seq=691, missing content). The suggested remediation chain dead-ends for local-only users:
    • engram cloud upgrade doctor --project <p> β†’ upgrade_blocked_legacy_mutation_manual, "manual-action-required"
    • engram cloud repair materialize-mutations --project <p> --dry-run β†’ tries to ping Postgres at localhost:5433 and fails, because there is no cloud store to connect to
    • Restoring the observation content locally via mem_update succeeds, but the legacy seq=691 queue row still blocks the doctor

There is no local-only path to inspect/normalize/quarantine a malformed legacy mutation when cloud was never configured β€” yet the mutation was enqueued anyway (see #478).

πŸ”„ Steps to Reproduce

  1. On engram 1.15.10 (Claude Code plugin MCP), call mem_session_summary with a full markdown summary β†’ observation persists with empty content (intermittent; hit once in this session)
  2. Upgrade binary to 1.20.0
  3. Run engram doctor β†’ blocked on sync_mutation_required_fields
  4. Run engram cloud upgrade doctor --project "<project>" β†’ upgrade_blocked_legacy_mutation_manual
  5. Run engram cloud repair materialize-mutations --project "<project>" --dry-run β†’ Postgres dial error (cloud not configured)
  6. Repair the observation locally with mem_update (content restored, verified via search) β†’ re-run engram doctor β†’ still blocked (seq=691 row untouched)

βœ… Expected Behavior

❌ Actual Behavior

  • Observation stored with empty content; cloud queue poisoned with an upsert missing required fields
  • doctor permanently blocked; the only repair command requires a Postgres cloud store that does not exist on this machine
  • Local mem_update fixes the data but not the queue row

πŸ’» Environment

  • OS: Windows 11 (amd64)
  • Agent: Claude Code (plugin MCP engram mcp --tools=agent)
  • Shell: Git Bash / PowerShell
  • engram: 1.15.10 at capture time β†’ 1.20.0 at diagnosis
  • Cloud: engram cloud status β†’ not configured

πŸ“„ Relevant Logs

[blocked] sync_mutation_required_fields β€” 1 finding(s) detected.
  - sync_mutation_payload_missing_required_fields: observation payload missing required fields: content
    evidence: {"entity":"observation","entity_key":"obs-c1cf8a5b698d835d","missing_fields":["content"],"op":"upsert","project":"claude migration","seq":691,"target_key":"cloud"}

$ engram cloud upgrade doctor --project "claude migration"
status: blocked
reason_code: upgrade_blocked_legacy_mutation_manual
message: manual-action-required: observation payload missing required upsert fields: content (seq=691 entity=observation op=upsert)

$ engram cloud repair materialize-mutations --project "claude migration" --dry-run
engram: cloudstore: ping postgres: failed to connect to `user=engram database=engram_cloud`:
	127.0.0.1:5433 (localhost): dial error: dial tcp 127.0.0.1:5433: connectex: No connection could be made

ℹ️ Additional Context

Related: #686 (empty prompt content poisons cloud push), #503 (single empty-content observation fails whole batch, no quarantine), #478 (mutations enqueued with no cloud target), #508 (DB maintenance toolset). The malformed seq=691 row is being kept in place on this machine as a live repro case.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions