Skip to content

feat: retain explicit deletion tombstones - #44

Merged
steipete merged 1 commit into
mainfrom
feat/tombstone-retention-contract
Jul 17, 2026
Merged

feat: retain explicit deletion tombstones#44
steipete merged 1 commit into
mainfrom
feat/tombstone-retention-contract

Conversation

@steipete

Copy link
Copy Markdown
Contributor

Summary

  • consume the private API Deleted []string feed and retain stable note tombstones with deletion source/reason
  • cascade note deletion state to transcripts, panels, and raw source objects; migrate and reconcile legacy tombstones
  • make portable snapshot imports destination-preserving merges by default, with exact replacement only through --replace
  • document the import contract and add a curated changelog entry

VISION.md does not exist in this repository, so there was no vision file to update.

Regression coverage

  • explicit private API delete feed tombstones notes and all retained children/source rows
  • missing-from-sync does not tombstone a note
  • unknown explicitly deleted IDs become stable stub tombstones
  • late child upserts inherit an existing parent tombstone
  • v1 databases migrate deletion provenance and child state
  • legacy snapshot tombstones reconcile during both merge and replace imports
  • merge retains destination-only rows and conflicting local payloads; --replace removes them
  • desktop-cache deleted_at cascades through retained children/source rows

Proof

  • make check
  • make smoke
  • deadcode -test ./...
  • git diff --check
  • autoreview: /Users/steipete/Projects/agent-skills/skills/autoreview/scripts/autoreview --mode local --stream-engine-output — clean, no accepted/actionable findings

Real binaries, same portable fixture:

binary / mode destination-only rows after import
origin/main, default legacy import 0
this branch, default merge 1
this branch, explicit --replace 0

Real binary deletion fixture:

behavior origin/main this branch
note tombstone 1 1
transcript tombstone unavailable (no child deletion columns) 1
raw source-object tombstones unavailable 2
sync result deletion count unavailable 1

Source-blind behavior validation also confirmed persisted merge output, local conflict preservation, exact replace behavior, note/transcript/source tombstone queries, and non-zero errors for missing paths and unknown import flags.

@github-actions github-actions Bot added the feat label Jul 17, 2026
@steipete
steipete merged commit fb0a337 into main Jul 17, 2026
11 checks passed
@steipete
steipete deleted the feat/tombstone-retention-contract branch July 17, 2026 21:21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ad72b81892

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

string(deletion.Source), deletion.Reason); err != nil {
return fmt.Errorf("tombstone note %s: %w", documentID, err)
}
for _, table := range []string{"transcript_chunks", "document_panels", "source_objects"} {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict document tombstones to document-scoped source rows

When a deleted document has people, including source_objects in this document-wide cascade also tombstones kind="person" rows: retainPeople stores those rows with the meeting's document_id but keys them by global person id. A later sync of the same person from another live document hits UpsertSourceObject and preserves the existing deleted_at, so the person remains marked deleted even though only one document was deleted; restrict the cascade to document-scoped kinds or use per-document person keys, and apply the same rule in reconciliation.

Useful? React with 👍 / 👎.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants