Trashing drafts

Since 1.21.0, trash-post lets an agent remove a draft it no longer needs, such as a reply draft it has superseded, and untrash-post lets it undo that. Before, a draft an agent made could only be removed by a person.

Trash only

trash-post never deletes permanently: emptying the trash stays a human action. If a site has the trash switched off (EMPTY_TRASH_DAYS of 0), wp_trash_post() deletes outright, so the ability refuses instead. Both abilities need delete_post on the post, the capability WordPress checks before trashing or restoring in wp-admin, and both take site_id.

Same reach as update-post

What can be trashed comes from the same per-type rules as create-post and update-post (see Menus, template parts and synced patterns), so the two cannot drift. Each rule has a trash list of statuses, defaulting to its update list, with auto-draft accepted wherever draft is. Posts, pages and other content types can be trashed while draft, pending or auto-draft, so published, scheduled and private posts are refused. Menus, template parts and synced patterns set the list empty and are refused in any status.

A rule with a trash list but empty create and update lists is trash-only: its drafts can be trashed and restored, but the type is not writable through create-post or update-post, and list-post-types does not report it as writable. LH Email uses this for compose drafts, since publishing a compose post sends it.

Restoring

untrash-post restores only what trash-post could have trashed: the status WordPress recorded at trashing (_wp_trash_meta_status) must be on the type’s trash list. A post that was live before a person trashed it stays a human restore. The post returns to its previous status rather than core’s default of draft, except that an auto-draft comes back as a draft.

Both abilities are idempotent: trashing a post already in the trash, or restoring one that is not, succeeds with a notice and changes nothing. Every trash and restore is recorded in LH Audit Trail as content.post_trashed or content.post_restored (staff only, kept 370 days).