bug(sync): acknowledged hard-delete tombstones are re-journaled on every cloud sync, adding one redundant chunk per run
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
Research direction
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.
Written by the indexing model from the issue text.
Description
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.
- Dominant language
- Go
- Stars
- 7.1k
- Forks
- 729
- Avg merge
- 8h 35m
- Merged PRs (30d)
- 319
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Gentleman-Programming/engram
-
status:needs-review type:bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Gentleman-Programming/engram#2138 · 1 comment ·
Maintainers usually reply within 1 day
-
status:needs-review
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Gentleman-Programming/engram#2065 ·
Maintainers usually reply within 1 day
-
bug(tests): Windows Bash /tmp warnings break Codex and ratchet assertionsPossibly taken @dnlrsls claimed this today. Openstatus:approved type:bug
Gentleman-Programming/engram#2190 · 1 assignee ·
Maintainers usually reply within 1 day
-
bug(cloud): isolated project_owned sessions are never enqueued, so their observations dead-letter on other machinesPossibly taken A pull request linked to this issue is open or already merged. Openstatus:needs-review type:bug
Difficulty 3/5 1-2 days Newbie friendliness 72/100
Gentleman-Programming/engram#2187 ·
Maintainers usually reply within 1 day
-
status:needs-review type:feature
Difficulty 5/5 Over a week Newbie friendliness 35/100
Gentleman-Programming/engram#2186 ·
Maintainers usually reply within 1 day
All issues in Gentleman-Programming/engram
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
slavakurilyak/awesome-ai-agents#880 ·
Maintainers usually reply within 1 day
-
后缀带有LTX的番号无法自动匹配Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
metatube-community/metatube-sdk-go#387 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
apache/openserverless#282 · 2 comments ·