Skip to content

Fix publish for new pages + homepage settings; add discard & status abilities (v0.4.2) - #19

Merged
richtabor merged 1 commit into
mainfrom
cursor/publish-fix-homepage-settings-ad2d
Sep 6, 2026
Merged

Fix publish for new pages + homepage settings; add discard & status abilities (v0.4.2)#19
richtabor merged 1 commit into
mainfrom
cursor/publish-fix-homepage-settings-ad2d

Conversation

@richtabor

Copy link
Copy Markdown
Owner

Critical Publish Fixes

From Codex dogfood transcript on richa8c22.wordpress.com:

The Bug

When publishing a new staged page (source_id=0) set as homepage via page_on_front, the page was left as draft while the setting pointed at it → public homepage 404.

Root Cause

Publish tried to set post_status=publish before removing _changeset_is_staged meta. The plugin's own cs_prevent_staged_publish guard then forced it back to draft. Changeset claimed success, but homepage stayed draft.

The Fix

  1. Internal flag bypass: Added $cs_publishing_changeset global flag so the guard allows publish during cs_publish_changeset
  2. Order matters: Clear staged markers before changing status to publish for new content
  3. Settings remapping: Apply settings with ID remapping after content is published (staged IDs → final live IDs)
  4. Accurate results: Verify final post_status is publish; track and return failed_items when any item fails

New Abilities

changesets/discard

Trash/discard an open changeset and delete all staged drafts. Clears preview. Needed because agents had to use raw WP REST to undo.

Example:

{"changeset_id": 123}

Returns:

{
  "changeset_id": 123,
  "status": "discarded",
  "deleted_count": 5
}

changesets/status

Setup discovery and readiness check. Returns plugin version, abilities registration status, current user capabilities, and open changeset count.

Example:

{}

Returns:

{
  "version": "0.4.2",
  "abilities_registered": true,
  "user_caps": {
    "manage_changesets": true,
    "approve_changesets": true,
    "publish_changesets": true
  },
  "open_changeset_count": 1
}

Use case: Agents should call this before create to verify Changesets + MCP Adapter are installed and active.

Enhancements

changesets/get includes full change context

Now returns staged_options, staged_styles, and style_variation — not just staged content items. Reviewers need the whole picture.

Example response:

{
  "changeset_id": 123,
  "uuid": "...",
  "title": "Home update",
  "status": "open",
  "preview_url": "...",
  "staged_items": [...],
  "staged_options": {
    "show_on_front": "page",
    "page_on_front": 456
  },
  "staged_styles": {...},
  "style_variation": "twilight"
}

Agent Documentation Improvements

Setup checklist (verify BEFORE asking for credentials):

  1. Are Changesets + MCP Adapter installed and active?
  2. Verify by checking if changesets/* abilities are available via MCP tools
  3. If missing: Ask permission to install, then install if allowed
  4. Only after plugins are active: Request Application Password / MCP connection

Why: Site URL alone ≠ MCP access. Need the adapter plugin + authenticated connection for changesets/* tools to appear.

Updated in README.md and readme.txt with paste-ready agent prompts.

Test Coverage

Added critical test case in TEST.md:

New page as homepage (publish + setting remap)

  1. Create new page via changesets/save (no source_id)
  2. Stage show_on_front=page and page_on_front=<staged_id>
  3. Approve and publish
  4. Verify:
    • Page has post_status='publish' (not draft)
    • Option page_on_front equals final live ID (remapped)
    • Homepage loads without 404
    • No _changeset_is_staged meta remains

Files Changed

  • includes/changesets.php: Fixed publish order, added discard & status functions
  • abilities/register.php: Added discard & status abilities; enhanced get with options/styles
  • changesets.php: Version bump to 0.4.2
  • readme.txt, README.md: Updated changelogs and agent guidance
  • TEST.md: Added critical test scenarios
  • BUILD.md: Updated spec with new abilities

Version

0.4.2

Ready to squash-merge.

Open in Web Open in Cursor 

…bilities

Critical fixes (v0.4.2):
- Publish: Clear staged markers BEFORE status change to prevent guard blocking
- Publish: Use internal flag to bypass guard during cs_publish_changeset
- Settings: Remap staged IDs to live IDs after content is published (order matters)
- Results: Track and return failed_items for accurate publish outcomes

New abilities:
- changesets/discard: Trash changeset and delete all staged drafts
- changesets/status: Readiness check (version, caps, open count)

Enhancements:
- changesets/get: Include staged_options, staged_styles, style_variation
- Agent docs: Front-load plugin install verification before credentials

Test coverage:
- New page as homepage scenario (the critical dogfood bug)
- Discard and status ability tests

Fixes homepage 404 when new staged page set as page_on_front.

Co-authored-by: Rich Tabor <rich@tabor.email>
Copilot AI lite review requested due to automatic review settings September 6, 2026 18:44
@richtabor
richtabor merged commit 762ae4d into main Sep 6, 2026
1 check passed
@richtabor
richtabor deleted the cursor/publish-fix-homepage-settings-ad2d branch September 6, 2026 18:45

Copilot AI 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.

🟡 Changes recommended

The new publish flow can still leave inconsistent state on partial failures (including closing a changeset as published) and the new status ability’s permissions/counting behavior need correction before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR targets a critical Changesets publish bug affecting newly staged pages used as the homepage, and extends the Abilities API surface with new discard and status endpoints while updating documentation/specs for v0.4.2.

Changes:

  • Fixes publish flow for new staged content (source_id=0) and adds settings ID remapping, plus partial-failure reporting.
  • Adds changesets/discard (trash + delete staged drafts) and changesets/status (readiness/status check) abilities.
  • Updates versioning and documentation (README/readme/BUILD/TEST) to reflect new behaviors and agent setup guidance.
File summaries
File Description
includes/changesets.php Adjusts publish ordering/guard bypass; adds discard and status helpers; returns partial failure details.
abilities/register.php Registers new abilities and expands changesets/get response with staged options/styles/variation.
changesets.php Bumps plugin version constant/header to 0.4.2.
BUILD.md Updates spec to document new abilities and publish behavior.
TEST.md Adds manual test scenarios for the fixed homepage publish case and new abilities.
README.md Updates agent prompt/checklist and “What’s new” to 0.4.2.
readme.txt Updates stable tag + changelog + agent setup guidance.
Review details

Suppressed comments (4)

includes/changesets.php:906

  • After a successful publish of a brand-new staged post, the staged markers (_changeset_is_staged/_changeset_id/CS_META_SOURCE) should still be cleared to avoid leaving the post treated as “staged” after it’s live. With the change above, the cleanup needs to happen here (after verification).
			$staged_to_live[ $staged_id ] = $staged_id;
			$source_ids[] = $staged_id;
			$published_new++;
		}

includes/changesets.php:916

  • Settings are applied (and _changeset_staged_options is deleted) even when some staged items failed to publish. That can persist settings pointing at missing/unpublished content and also makes it impossible to retry publish with the original staged options.
	// Apply settings with ID remapping AFTER content is published.
	$options = cs_get_staged_options( $changeset_id );
	if ( $options ) {
		foreach ( $options as $key => $value ) {
			// Remap staged IDs to live IDs for settings that reference posts.

includes/changesets.php:961

  • The changeset is marked as published and the preview cookie is cleared even when failed_items is non-empty. That prevents discarding/retrying (cs_discard_changeset forbids published) and can hide remaining staged drafts that didn’t apply.
	update_post_meta( $changeset_id, '_changeset_status', 'published' );
	update_post_meta( $changeset_id, '_changeset_published_at', gmdate( 'c' ) );
	update_post_meta( $changeset_id, '_changeset_published_by', get_current_user_id() );

	cs_clear_preview_cookie();

includes/changesets.php:974

  • cs_publish_changeset now returns extra keys (changeset_id/status/published_new_count and, on partial success, failed_items/partial_success). The registered output_schema for the changesets/publish ability still only declares applied_count and source_ids, which can cause schema/contract drift for API consumers.
	$result = array(
		'changeset_id'        => $changeset_id,
		'applied_count'       => $applied,
		'published_new_count' => $published_new,
		'source_ids'          => $source_ids,
		'status'              => 'published',
	);

	if ( ! empty( $failed_items ) ) {
		$result['failed_items'] = $failed_items;
		$result['partial_success'] = true;
	}
  • Files reviewed: 7/7 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread abilities/register.php
Comment on lines +409 to +413
),
),
'execute_callback' => 'cs_ability_get_status',
'permission_callback' => '__return_true',
'meta' => array(
Comment thread abilities/register.php
Comment on lines +478 to 492
$staged_options = cs_get_staged_options( $changeset_id );
$staged_styles = cs_get_staged_global_styles( $changeset_id );
$style_variation = cs_get_staged_style_variation( $changeset_id );

return array(
'changeset_id' => $changeset_id,
'uuid' => cs_get_changeset_uuid( $changeset_id ),
'title' => $changeset->post_title,
'status' => cs_get_changeset_status( $changeset_id ),
'preview_url' => cs_get_preview_url( $changeset_id ),
'staged_items' => $staged_items,
'changeset_id' => $changeset_id,
'uuid' => cs_get_changeset_uuid( $changeset_id ),
'title' => $changeset->post_title,
'status' => cs_get_changeset_status( $changeset_id ),
'preview_url' => cs_get_preview_url( $changeset_id ),
'staged_items' => $staged_items,
'staged_options' => $staged_options ? $staged_options : array(),
'staged_styles' => $staged_styles ? $staged_styles : null,
'style_variation' => $style_variation ? $style_variation : null,
);
Comment thread includes/changesets.php
Comment on lines +870 to +875
// Promote brand-new staged content to live publish.
// Clear staged markers FIRST to prevent guard from blocking.
delete_post_meta( $staged_id, '_changeset_is_staged' );
delete_post_meta( $staged_id, '_changeset_id' );
delete_post_meta( $staged_id, CS_META_SOURCE );

Comment thread includes/changesets.php
Comment on lines +1548 to +1564
// Count open changesets.
$open = get_posts(
array(
'post_type' => 'changeset',
'post_status' => 'draft',
'posts_per_page' => 1,
'meta_query' => array(
array(
'key' => '_changeset_status',
'value' => 'open',
),
),
'fields' => 'ids',
)
);
$status['open_changeset_count'] = count( $open );

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants