Working copy ability reference
Reference for the GoBuildWP Pro 1.12.4 source. Installed schemas and policy remain authoritative.
This Working copy ability reference covers how an agent edits supported captured post-backed state in a draft copy of a live page, previews the difference and publishes it back onto the original. Publishing writes onto the same post, so the page keeps its ID, URL, publication date, comments and SEO history, and a supported captured before-image can provide recovery. A publish explicitly accepted with accept_irreversible=true has no before-image in the ledger and cannot be rolled back.
Read-only, write and destructive groups describe the source annotations. They do not establish a minimum safety profile, human approval or undo support. Those controls are separate: check the installed ability, the connected user and the active site policy before calling it. A read can still return sensitive data. These pages are not evidence that every operation passed an end-to-end runtime test.
What Working copy needs before these load
Working copy is part of GoBuildWP Pro and has no companion-plugin gate. It copies content, title, excerpt, terms and eligible post meta, excluding sensitive keys and derived caches. Mosaic custom tables and uncaptured live global or template state are excluded. Global classes, palettes, templates and assignments or other site-wide stores are separate; editing those while working on a draft can affect the live site. Most calls check that GoBuildWP is switched on and that the user has edit_posts, then edit_post on both the copy and the original (wppilot_working_copy_forbidden). Reading or changing the draft-first setting needs manage_options. The yoast-rewrite-republish method uses Yoast Duplicate Post's Rewrite and Republish copy when that plugin is active, for published posts.
- Working copy editions
- pro
- Agent skills shipped
working-copy
Draft-first: refusing edits to live pages
With the wppilot_pro_draft_first option on (it is off by default), builder writes aimed at a published, private or scheduled post are refused with wppilot_pro_draft_first (HTTP 409). The message names the next call: wppilot/working-copy-create, or the id of the copy that already exists. The check runs before the approval queue, so a refused edit never turns into an approval request that would write to the live page later. It applies to agent transports; PHP, WP-CLI and approved replays are not affected.
Three checks before a copy overwrites the original
Without confirm=true, publish returns wppilot_working_copy_confirm_required with the diff: content and title changed or not, and how many meta keys would be added, changed or removed. If the live post was edited after the copy was taken, it returns wppilot_working_copy_original_changed until accept_newer_original is true. If the post is too large for the change ledger to snapshot, it returns wppilot_working_copy_not_reversible until accept_irreversible is true.
What a copy leaves behind
The copy carries every meta key except edit locks, old-slug records, derived builder caches such as _elementor_css and _uag_page_assets, which the builder regenerates, and keys the ledger treats as sensitive. It records its original in _wppilot_working_copy_of. After publishing, the copy goes to the trash and the builder's CSS caches for the original are cleared.
Before accepting the result
Preview the copy, review conflicts with newer original edits, obtain publication approval, then inspect the native editor and public page. Post-backed captured state excludes Mosaic custom tables and uncaptured live global or template state.
Representative call sequence
This sequence describes the documented calls and checks to perform. It is not a recorded result from an installed WordPress site. Inspect returned errors and partial results, then verify the saved values and affected output before proceeding.
Rework the hero on a busy home page built in Elementor without visitors seeing half-finished edits.
- 01
wppilot/working-copy-createMakes a draft copy of the home page and returns its copy_id and preview URL. - 02
wppilot/elementor-edit-elementEdits the hero on the copy, using copy_id as post_id; the live page is untouched. - 03
wppilot/working-copy-previewReports what publishing would change on the live page, including which meta keys differ. - 04
wppilot/working-copy-publishWith confirm=true, writes the copy onto the original post, trashes the copy and records supported recovery state. Inspect the before-image contract; accept_irreversible=true deliberately permits publishing without usable recovery.
Working copies in practice
Which edits draft-first stops, and which it lets through
Draft-first sits in front of the same three entry points as the approval queue (the MCP Adapter, the free plugin's REST shim and its MCP transport) and runs one step earlier, so a refused builder write never becomes a queued request. The list of guarded calls starts from every builder write the change ledger knows how to target by post, and adds the builders it does not map yet; where a builder accepts post as an alias of post_id, both are checked. A developer can extend the list with the wppilot_pro_draft_first_targets filter for a builder of their own.
Display-condition writes are deliberately not guarded. A condition decides where a template appears rather than what it contains, so staging it on a copy that nobody ever sees would prove nothing. The guard is aimed at page builder writes, so turning draft-first on is not a general content freeze; pair it with a safety profile or approvals when that is what the site owner wants.
The draft-first map guards the free plugin's direct gutenberg-write-content call by target_id or post_id. Queued Gutenberg composition has separate preparation and execution, and Kadence pattern insertion is a separate direct operation. Check each installed write path and its target requirements; this map is not evidence that every block edit passes through one guarded call. Elementor, Bricks, Divi 5, Beaver Builder and Oxygen writes are listed one by one, including page-level settings and, for Beaver Builder, applying a template to a page. An agent that receives the draft-first refusal should create the copy the message names, or reuse the copy id it gives, and repeat the same builder call against that id.
Posts a working copy cannot be made from
After a copy is published or discarded it is in the trash, and any further call on it returns wppilot_working_copy_trashed. If the original itself was trashed or deleted while the copy was open, publishing returns wppilot_working_copy_original_missing with HTTP 404, and the copy is the only place the new work survives: restore the original first, or publish the copy as a new page by hand.
- wppilot_working_copy_source_unusable: the source is trashed, an auto-draft or in inherit status, or it is a revision, attachment or menu item.
- wppilot_working_copy_is_copy: the id given is already a working copy. Edit it directly and publish it; copies of copies are refused.
- wppilot_working_copy_cannot_create (HTTP 403): the user can edit the original but cannot create posts of its type.
- wppilot_working_copy_yoast_unavailable and wppilot_working_copy_yoast_refused: the yoast-rewrite-republish mechanism needs Yoast Duplicate Post with Rewrite & Republish active, and that plugin only copies a published post that has no open copy. Leaving mechanism out uses GoBuildWP's own copy instead.
Undoing each working-copy step
Each step is recorded in the change ledger, and wppilot/rollback-change can reverse it while a before-image exists. Undoing a create moves the copy to the trash. Undoing a discard takes the copy out of the trash again. Undoing a publish restores the original from the snapshot taken just before the write, which holds its captured content, title, excerpt, eligible meta and taxonomy state. Sensitive keys and excluded derived caches are outside that capture; verify builder data and SEO fields after recovery. The exception is an original too large for the ledger to keep a before-image: the publish is refused with wppilot_working_copy_not_reversible, and repeating it with accept_irreversible=true publishes with no way back through the ledger, so take a backup of the original first. Changing the draft-first setting is recorded as a settings change and can be reversed the same way. See change ledger and rollback for how to find the change id.
Only the publish purges the page cache, and only for the original page, because creating and discarding drafts changes nothing a visitor can see. If a rollback of a publish does not show on the live page, clear the page cache for that URL by hand before assuming the restore failed.
Questions about Working copy
Will publishing a working copy change the page's URL or lose its comments?
No. The copy is written back onto the original post, so its ID, URL, date and comments stay as they were.
What if someone edits the live page while my copy is open?
Publishing stops with wppilot_working_copy_original_changed rather than discard their edit. Make a fresh copy, or pass accept_newer_original=true to overwrite it deliberately.
Working copy reads
| Ability | What it does |
|---|---|
wppilot/working-copy-listList Working Copies | Lists the open working copies you can edit (at most 100, newest first), each with its original, when it was taken, whether the original has changed since, and its preview URL. Pass source_id to find the copy of one post. |
wppilot/working-copy-previewPreview a Working Copy | Returns the preview URL of a working copy and what publishing it would change on the live post: whether content, title and excerpt differ (with sizes), which meta keys would be added, changed or removed (with sizes), which taxonomies' terms differ, and whether the live post was edited after the copy was taken. Writes nothing. Call it before wppilot/working-copy-publish, and open preview_url to check the page. |
Working copy writes
| Ability | What it does |
|---|---|
wppilot/working-copy-createCreate a Working Copy | Makes a draft copy of a page or post so it can be edited without touching the live page: same post type and parent, the content, title, excerpt, terms, featured image and every builder and field meta key (Elementor, Bricks, Divi, Beaver Builder, Oxygen, Breakdance, Etch, WPBakery, Flatsome, block builders). Edit locks, old-slug and trash bookkeeping, per-post builder CSS caches (rebuilt for the copy) and secrets are not copied. If the post already has a working copy, returns that one instead of making a second. mechanism "yoast-rewrite-republish" uses Yoast Duplicate Post's Rewrite & Republish copy when that plugin is active (published posts only). Then edit the copy with the builder abilities using the returned copy_id as post_id. |
wppilot/working-copy-settingsWorking Copy Settings | Reads, and with draft_first set, changes the draft-first setting (option wppilot_pro_draft_first, off by default). While it is on, builder write abilities refuse to edit a published, private or scheduled post directly and tell the agent to call wppilot/working-copy-create first; writes to working copies and drafts are unaffected. Requires site-management rights. Omit draft_first to read the setting without changing it. |
Destructive Working copy calls
| Ability | What it does |
|---|---|
wppilot/working-copy-discardDiscard a Working Copy | Moves a working copy to the trash without publishing it. The live post is not touched. Requires confirm=true; wppilot/rollback-change restores the copy. |
wppilot/working-copy-publishPublish a Working Copy | Writes a working copy back onto its ORIGINAL post — content, title, excerpt, terms and the copied builder/field meta — so the live page keeps its ID, URL, date, comments and SEO history, then moves the copy to the trash, clears the builder's CSS caches for the page and purges the page cache. Requires confirm=true. The change ledger records a before-image of the original, so wppilot/rollback-change undoes the publish; when the original is too large for a before-image the publish is refused unless accept_irreversible=true, and a publish made that way cannot be rolled back. Refuses when the live post was edited after the copy was taken unless accept_newer_original=true, because publishing would discard those edits. Call wppilot/working-copy-preview first. |