Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

bug(obsidian): obsidian-export leaves stale notes for hard-deleted and renamed observations

Aperta
#1,900 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@Yi-111-a ci sta già lavorando.

Dal 17/10/2026.

  • #1927 di @Yi-111-a — aperta

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
62/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
go
Ambito
cli, data

Direzione di ricerca

Start in internal/obsidian/exporter.go: the cleanup loop only visits rows from store.Export() with DeletedAt set, and the export loop overwrites state.Files[obs.ID] without comparing the old path. Reproduce with the numbered steps (hard delete, then a PATCH rename, then export) and check .engram-sync-state.json. Done when hard-deleted and renamed notes are removed or moved, orphaned hubs are pruned, and the export output reports the deletions.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

Existing Issue Search
  • I searched existing issues and will add evidence to a canonical tracker when applicable.
📝 Observed Consequence

engram obsidian-export leaves Markdown notes in the vault that no longer correspond to any live observation, and keeps reporting Deleted: 0. Two triggers:

  1. Hard-deleted observations (engram delete <id> --hard, engram delete project <name> --hard, or any hard deletion that happens between two exports): the note, and its session hub, stay in the vault forever. Their entry also stays in .engram-sync-state.json.
  2. Renamed observations (title updated, so the slug changes): the next export writes a new file and overwrites the state entry with the new path. The old file stays on disk and is no longer tracked by the state, so not even a state-based cleanup can find it.

Soft deletion works correctly: engram delete <id> followed by an export removes the note (Deleted: 1).

On a real vault, after a bulk hard deletion and normal use, this accumulated several hundred stale notes plus orphan session and topic hubs, all shown in Obsidian search and Graph View as if they were live memories.

🔄 Steps to Reproduce
  1. Isolated store and vault: T=$(mktemp -d); e() { HOME="$T/home" ENGRAM_DATA_DIR="$T/data" engram "$@"; }
  2. e save "keep me" "first body" --project demo and e save "hard gone" "second body" --project demo
  3. e obsidian-export --vault "$T/vault" --all --graph-config skip → Created: 2
  4. e delete 2 --hard
  5. e obsidian-export --vault "$T/vault" --all --graph-config skip → Deleted: 0; engram/demo/manual/hard-gone-2.md still exists and .engram-sync-state.json still maps "2" to it.
  6. Rename observation 1 through the HTTP API: e serve 17499 &, then curl -X PATCH 'localhost:17499/observations/1?expected_project=demo' -H 'content-type: application/json' -d '{"title":"keep me renamed"}', then stop the server.
  7. e obsidian-export --vault "$T/vault" --all --graph-config skip → Created: 1, Deleted: 0; both keep-me-1.md and keep-me-renamed-1.md exist, and the state only knows keep-me-renamed-1.md.
✅ Expected Behavior

After an export, the vault contains exactly one note per live observation:

  • Notes tracked in the state whose observation no longer exists in the store at all (hard-deleted) are removed, like soft-deleted ones.
  • When an observation's target path changes, the previously tracked file is removed (or moved) before the state entry is overwritten.
  • Session/topic hubs that no longer reference any live observation are removed.
❌ Actual Behavior
# after hard delete of #2
Obsidian export complete
  Created: 0
  Updated: 0
  Deleted: 0
  Skipped: 1
  Hubs:    1
engram/demo/manual/hard-gone-2.md   <- still present
engram/demo/manual/keep-me-1.md

# after renaming #1
  Created: 1
  Updated: 0
  Deleted: 0
engram/demo/manual/keep-me-renamed-1.md
engram/demo/manual/keep-me-1.md     <- stale, untracked
engram/demo/manual/hard-gone-2.md   <- still present
Operating System

macOS

Release Version (Report Context)

3.4.0

Agent / Client

Other

📋 Relevant Logs

No response

💡 Additional Context

Client: Pi (via gentle-engram); the exporter is client-independent.

Current main (8589a5f), internal/obsidian/exporter.go:

  • The cleanup loop only visits rows returned by store.Export() that have DeletedAt != nil. Hard-deleted rows are not returned, so their state.Files entries are never reconciled.
  • The export loop computes relPath from the current slug and assigns state.Files[obs.ID] = relPath without comparing it with the previously tracked path.

A possible approach: after the export loop, remove every tracked state.Files entry whose ID is not a live observation, and when the tracked path for a live ID differs from the new relPath, delete the old file (with the same containment checks used today).

Workaround: compare the state's file IDs with live observation IDs, then delete the orphaned files and prune the state by hand, after taking a backup.

Lingua principale
Go
Stelle
7.1k
Fork
729
Merge medio
10h 43m
PR unite (30g)
332

Preparare l'ambiente

Apri in Codespaces

Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Gentleman-Programming/engram

Tutte le issue di Gentleman-Programming/engram

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.