bug(sync): acknowledged hard-delete tombstones are re-journaled on every cloud sync, adding one redundant chunk per run
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
Línea de trabajo
Start by tracing the cloud sync export path that creates mutations from hard-delete tombstones, then inspect the journal acknowledgement and deduplication logic. Use the provided SQLite queries to reproduce the repeated delete rows and verify their acknowledgement state. Done means an acknowledged tombstone is not re-queued, pending reaches zero, and an immediate sync creates no additional chunk.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Existing Issue Search
- I searched existing issues and will add evidence to a canonical tracker when applicable.
📝 Observed Consequence
Cloud sync for one project never settles. Seven hard-delete tombstones whose rows are already acknowledged are re-queued on every engram sync --cloud, so the pending counter never reaches 0 and each sync appends one more redundant chunk to both local and remote storage. Over time the journal grows without bound while nothing new is pending: 13 entity_keys already hold more than 100 journal rows, seven of them hold ~3.000 each.
🔄 Steps to Reproduce
- Use a store that was migrated from an older release (binary
3.6.1-0.20261026063815-f15b94ab0394). - Inspect the journal churn:
sqlite3 ~/.engram/engram.db \ "SELECT entity_key, count(*) FROM sync_mutations GROUP BY 1 HAVING count(*) > 100 ORDER BY 2 DESC;" - Confirm the entities no longer exist and that their tombstones are recorded:
sqlite3 ~/.engram/engram.db \ "SELECT count(*) FROM observations WHERE sync_id IN (<the churned keys>);" -- 0 sqlite3 ~/.engram/engram.db \ "SELECT count(*) FROM sync_delete_tombstones WHERE entity_key IN (<the churned keys>);" -- 7 - Note the chunk counts, then sync once:
engram sync --cloud --project <project> --status # Local chunks: 9023 / Remote chunks: 9021 engram sync --cloud --project <project> # Mutations: 7 engram sync --cloud --project <project> --status # Local chunks: 9024 / Remote chunks: 9022 - Re-read the journal: seven new
seqrows with the sameentity_keys andop='delete', all acknowledged, and the previous generation already acked. Repeat step 4 and it happens again with freshseqs (observed chain84146 → 84197 → 84330 → 84357).
✅ Expected Behavior
An acknowledged hard-delete tombstone is terminal. Once its mutation has been exported and acked, it is not queued again, pending reaches 0 for the project, an immediate re-sync is a no-op, and no additional chunk is created.
❌ Actual Behavior
Every sync re-materializes the same seven deletes with a new seq and a new occurred_at, so:
pendingnever drains for that project (7before and after each successful sync).- One extra chunk per run on both sides (local
9023 → 9024, remote9021 → 9022; the two-sided gap stays constant, so remote is consistent — nothing is lost, it is duplicated). - The journal and the chunk store grow monotonically: 84.331 journal rows total (84.267 acked), of which 21.683 belong to these seven keys alone (2.966–3.171 rows each). Store size reached 809 MB.
sync_mutations.dispositionis'pending'for all 84.170 rows, so it cannot be used to distinguish settled rows.
Operating System
Windows (WSL)
Release Version (Report Context)
engram 3.6.1-0.20261026063815-f15b94ab0394
Agent / Client
Other
📋 Relevant Logs
# journal churn per entity_key (top rows)
obs-eaf9a2408f8333be | 3260 | 2026-10-26 18:40:10.664839435
obs-e1049f40d8eedd5c | 3260 | 2026-10-26 18:40:10.664691018
obs-b1840168fbbb9355 | 3260 | 2026-10-26 18:40:10.664518854
obs-a6f585b5116f8dc9 | 3260 | 2026-10-26 18:40:10.664296821
obs-f225868ff6ae2703 | 3171 | 2026-10-26 18:40:06.818199303
# op distribution for the seven churned keys
delete | 21683 | 21676
upsert | 7 | 7
# payload of the newest generation (seq 84357..84363), by design identical to the first
{"deleted": true, "hard_delete": true, "deleted_at": "2026-10-14 12:20:07"}
# same entity_keys, generations apart
obs-21959bc3c54b3164 | 3158 rows | first_seq 35671 | last_seq 84357
obs-f225868ff6ae2703 | 3171 rows | first_seq 24948 | last_seq 84363
# three consecutive syncs, each one chunk
Exporting memories for project "<project>" to cloud...
Created chunk d04ea78c ... Mutations: 7
Created chunk 3452f824 ... Mutations: 7
Created chunk 421c3a44 ... Mutations: 7
💡 Additional Context
- Each re-queued row is acknowledged almost immediately by the cloud, so this is not a rejected write: the export step itself regenerates the mutation from the tombstone/absence of the entity instead of honoring the already-settled journal row. The dedupe boundary looks like it keys on the entity instead of the settled
(entity, entity_key, op)generation, and stamps a freshoccurred_at/seqeach time. - Practical effect:
engram sync --cloudcannot be used as a convergent "flush" operation on such a store — every call makes the store slightly bigger and never reports zero pending. I stopped re-syncing the affected project deliberately. - Related, not duplicates: #1851 (hard project delete writes no tombstone), #1230 (delete on an unenrolled project orphans its pending upsert), #1104 (unbounded journal growth), #1864, #1424.
- A supported way to retire a settled tombstone (or to stop re-exporting it) would be enough; no manual DB surgery is documented.
- Lenguaje dominante
- Go
- Estrellas
- 7.1k
- Forks
- 729
- Merge medio
- 10 h 12 min
- PR fusionados (30 d)
- 272
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Gentleman-Programming/engram
-
status:needs-review
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
Gentleman-Programming/engram#2210 ·
Los mantenedores suelen responder en 1 día
-
status:needs-review type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Gentleman-Programming/engram#2206 ·
Los mantenedores suelen responder en 1 día
-
Passive observation titles get cut in the middle of a multibyte characterPosiblemente ocupada @dnlrsls la tomó hace 1 día. Abiertostatus:approved type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Gentleman-Programming/engram#2205 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
status:needs-review type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
Gentleman-Programming/engram#2204 ·
Los mantenedores suelen responder en 1 día
-
status:needs-review type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Gentleman-Programming/engram#2138 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de Gentleman-Programming/engram
Issues similares
-
netrc credential source accepts a password with an embedded CR/LF that every other source rejectsAbiertoagent-butler-finding bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
jordansmall/spindrift#6268 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 7 días
-
kind/bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
kmesh-net/kmesh#1979 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
caddyserver/caddy#8314 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100