Hosted onhoraciohdev.dev.hyper.mediavia theHypermedia Protocol

Deleted Document Parent Embed Cleanup

Problem

When a user deletes a document, the parent document that embeds it should stop pointing at content that no longer exists. Today, a parent can still show a document card, content embed, block link, or comments embed for the deleted document, which creates a broken “deleted document” experience and leaves users with manual cleanup work.

The final product behavior should make deletion feel complete. If the deleted document is represented in its parent, the parent reference should be removed as part of the delete workflow. If that embed was being used as a container for other blocks, those blocks should not be lost; they should remain in the parent at the same level where the embed used to be.

Solution

The final result is a durable cleanup step that runs after the document delete succeeds. The cleanup looks at the deleted document’s parent and removes any embed block in that parent that points at the deleted document. It matches the document itself, not a specific version or block reference, so links like hm://uid/path, hm://uid/path?v=..., and hm://uid/path#block-id are treated as references to the same deleted document.

cleanup machine

When the parent is a published document and it contains an embed for the deleted document, the system creates a clean new version of the parent document as part of the delete cleanup. That new version removes the stale embed so readers no longer see a deleted-document block in the parent.

When the parent is a published document and the removed embed has child blocks, the cleanup creates a clean new parent document version that removes the embed and lifts the embed’s children into the embed’s previous position. The children keep their content and order; only the deleted-document wrapper is removed.

When the parent has a draft, the cleanup updates the parent draft instead of publishing a new parent document version. The embed block pointing at the deleted document is removed from the draft so the author continues editing a clean parent draft.

When the parent draft’s embed block has child blocks, the cleanup removes the embed from the draft and lifts its children into the same level where the embed was. The author keeps the nested work without keeping the stale deleted-document embed.

When the parent has no embed pointing at the deleted document, the cleanup does nothing. The delete operation should not create a new parent version or rewrite a draft if there is no stale reference to remove.

When the parent has a self-query block, the cleanup also does nothing. Query blocks are dynamic views rather than direct embed references to the deleted document, so they should not be rewritten by this cleanup job.

How to test

    Delete a child document whose parent contains a matching embed.

    Confirm published-parent cleanup still publishes the parent update.

    Confirm parent-draft cleanup still removes embeds, preserves children, broadcasts draft_externally_modified, and auto-reloads the draft.

    Force a transient cleanup failure, then enqueue another cleanup; confirm the second cleanup waits until the first retry either succeeds or reaches failedNeedsAttention.

Scope

The project includes the post-delete cleanup workflow for direct parent references to the deleted document. It covers published parents and draft parents, and it preserves child blocks under removed embeds by lifting them into the parent’s block tree.

The first complete version should include the durable cleanup job, document-version publishing for published parents, draft mutation for draft parents, retry behavior for transient failures, and tests for the delete scenarios listed above. The implementation should be focused on direct parent cleanup only and should avoid broader document-machine refactors unless they are required to make draft cleanup automatic and reliable.

A practical implementation path is to first land the shared cleanup planner and published-parent flow, then finish the draft-parent flow so open drafts reflect the cleanup automatically, and finally verify the edge cases around no-op parents and self-query blocks.

Rabbit Holes

It would be easy to turn this into a general-purpose document repair system, but the project should stay focused on stale embeds created by deleting a document. Recursive cleanup of every descendant reference, full query invalidation semantics, and a generalized external draft reconciliation framework can wait unless they are strictly necessary for the parent draft UX.

Another tempting path is to treat every stale visual reference as something to rewrite. This project should not do that. Self-query blocks and other dynamic structures are outside the cleanup target because they do not directly embed the deleted document as a removable block.

No Gos

The cleanup must not delete child blocks that belong under a removed embed. Those blocks are user content and must be preserved by lifting them into the parent.

The cleanup must not publish a parent document when the parent has a draft. In that case, the draft is the user’s active source of truth and should be updated instead.

The cleanup must not create a new parent version or rewrite a draft when there is no embed pointing at the deleted document. No-op cases should remain no-op.

The cleanup must not rewrite self-query blocks. Queries should continue behaving dynamically and should not be converted into cleanup edits.

Do you like what you are reading? Subscribe to receive updates.

Unsubscribe anytime