Skip to content

bug(obsidian): sync silently ignores observations from GET /export #1460

Description

@dnlrsls

📝 Bug Description

The private Obsidian plugin's sync.ts expects GET /export to return notes and count. The server's export payload instead contains version, exported_at, sessions, observations, prompts, and relations. The plugin treats absent notes as an empty array, so an export with observations can produce zero note writes and still advance local sync state. The user has chosen to maintain the plugin rather than retire it.

🔄 Steps to Reproduce

  1. Supply plugin/obsidian/src/sync.ts with a mocked GET /export response shaped like the actual store.ExportData: include one observation in observations, with no notes or count keys.
  2. Run the real sync.ts code in memory with mocked Obsidian/Vault imports and fetch; record note writes, the returned count, and sync-state write attempts. No active Engram server or user vault is needed.
  3. Observe zero note writes despite the exported observation. Independently, run go test ./internal/server -run '^TestExportHonorsProjectQueryScope$' -count=1 -v to confirm the server-side export test passes against a temporary store; that Go test alone does not execute the plugin.

✅ Expected Behavior

The supported Obsidian synchronization path should consume the actual export contract and create/update the corresponding note for an exported observation, or fail explicitly without marking the run successful or advancing sync state when the response is incompatible. A regression test should execute the plugin against a representative server export fixture and fail on the current code.

❌ Actual Behavior

With a mock export containing one observation, executing the real plugin source produced noteWrites: 0, result.total === undefined, and one sync-state file write attempt. The server-side scoped export test passed, so it does not detect this client/server mismatch. This reproduction used mocks; it is not a full Obsidian runtime test.

Operating System

Windows

Engram Version

2.2.1 (installed CLI and source baseline used for reproduction)

Agent / Client

Other

📋 Relevant Logs

go test ./internal/server -run '^TestExportHonorsProjectQueryScope$' -count=1 -v
# Observed: test passed, exit 0.
# In-memory sync.ts harness observations (summarized, not verbatim stdout):
# noteWrites=0; result.total=undefined; state-file write attempts=1.

💡 Additional Context

internal/store/store.go defines the export payload, while plugin/obsidian/src/sync.ts reads the incompatible notes/count shape and defaults missing notes to []. Keep the resolution at the client/server contract boundary; do not add a redundant parallel representation or silently accept empty payloads. The Obsidian plugin has no existing integration harness, and this reproduction did not use a real vault. GET /export?since=... semantics were not dynamically verified here and should not be claimed fixed by this report.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions