Skip to content

fix: resolve Codex review findings #1-5 (P1) - #60

Merged
zackkatz merged 2 commits into
developfrom
fix/codex-review-findings
Jul 23, 2026
Merged

fix: resolve Codex review findings #1-5 (P1)#60
zackkatz merged 2 commits into
developfrom
fix/codex-review-findings

Conversation

@zackkatz

@zackkatz zackkatz commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

Codex's adversarial review of the merged range 602ae77...b089815 (BLOCK-29, BLOCK-33, BLOCK-34, BLOCK-35) returned five P1 findings. All five were verified against source before fixing — all five are genuine, no false positives.

# File Finding Fix
1 class-template-manager.php:316 update_template() ignored WP_Error from wp_set_object_terms() while creating a new override, leaving an orphaned post on failure Check both term-assignment calls (wp_theme, and wp_template_part_area for parts); on failure, delete the freshly-inserted post and return the WP_Error
2 class-pattern-manager.php:747 create_pattern() validated title before sanitizing, so a whitespace-/markup-only title (e.g. " ", "<script></script>") that sanitizes to '' was accepted, silently creating a nameless pattern Sanitize with sanitize_text_field() first, then check the sanitized value for emptiness
3 class-pattern-manager.php:858 create_pattern() always returned a core/block reference, even for an unsynced pattern — but core/block is WordPress's live, propagating synced-block reference, wrong for a one-off reference is now returned only when sync_status === 'synced'. For unsynced, the response instead includes insert_hint: {tool: "insert_pattern", params: {pattern_id, synced: false}} (verified Block_Writer::insert_pattern() already supports synced:false against any pattern_id independent of the pattern's own sync-status meta). TS CreatePatternResponse (src/types.ts) and the create_pattern tool description (src/tools/patterns.ts) updated to match. The synced case is unchanged — backward compatible.
4 class-tool-executor.php:151 Abilities path for list_block_types never forwarded include_supports — silently dropped on the Abilities/MCP-Adapter transport while REST and the npm MCP server honored it Forward include_supports into the REST-handler params
5 class-tool-executor.php:194 Abilities path for list_patterns ignored category and dropped categories from the response Forward category into the REST-handler params; include categories in the returned array

Findings 4 and 5 are the same REST-vs-Abilities parity bug class fixed twice already in this range (BLOCK-34, BLOCK-35). Per the review request, the structural audit is now generalized: ToolExecutorParityAuditTest::test_every_manifest_input_property_is_referenced_by_its_tool_executor_method() reflects over every Tool_Executor::execute_*() method and asserts every manifest-declared input_schema property for that tool is referenced in the method body. It documents two narrow, deliberate exemptions rather than silently special-casing them:

  • Wholesale-forwarding tools (create_post, create_pattern, upload_media, list_terms, list_posts, get_post_info, edit_block_tree, update_post, yoast_update_seo) — these forward $input verbatim (minus an explicit unset()) to the REST handler, so "does the property name appear as a literal" is the wrong question for them by construction.
  • update_block's block_name — a genuinely new finding surfaced while writing this test, not the same bug class. It's a client-side-only enrichment selector (src/enrichers.ts) with no REST/PHP equivalent; the npm MCP server derives computed fields (e.g. CBP's codeHTML) on the client before sending only the already-enriched attributes over the wire, so Tool_Executor has nothing to forward it to. This is a real, standing gap (an Abilities-path caller doesn't get automatic enricher-derived fields), but porting enrichment to PHP is a separate feature, not a wiring fix — documented in the test rather than silently exempted or force-fixed here.

ListToolsAbilityParityTest adds behavioral coverage on top of the structural check, proving include_supports/category actually change the returned data (not just that the property name appears in the method body).

Verification

All 5 findings are pinned by tests — none required a manual-only verification note. Visible red/green git history (unsquashed):

  • 2cc44cd test(codex-review): pin all 5 confirmed P1 findings [red]
  • 258c143 fix(codex-review): resolve all 5 confirmed P1 findings [green]

Full local gate, all green:

composer test    → 1425 + 28 + 11 + 5 = 1469 tests, 0 failures
composer lint     → 0 errors, 0 warnings
composer analyze  → [OK] No errors (PHPStan)
npm test          → 55 files / 859 tests passed
npx tsc --noEmit  → clean
manifest drift    → npx tsx scripts/export-abilities-manifest.mjs; git diff → tool count unchanged (33), only the create_pattern description line changed (finding #3)
npm run build     → bundle regenerated + copied into wordpress-plugin/gk-block-mcp/assets/mcp-server/index.cjs

No Siteminter smoke test in this PR (not required per the assignment — the fixes are fully covered by the tests above, and staging validation is happening separately). No Linear issue exists for this batch (Codex review, not a tracked issue); noting this PR as a comment on BLOCK-31/33/34.

Claude-Session: https://claude.ai/code/session_013YcSbKroBJjPanX3okQrT3

Summary by CodeRabbit

  • New Features

    • Pattern creation responses now distinguish between synced and unsynced patterns, providing either an insert-ready reference or follow-up insertion guidance.
    • Block type listings can include support details when requested.
    • Pattern listings support category filtering and include available categories.
  • Bug Fixes

    • Improved title sanitization and validation.
    • Failed template taxonomy assignments now roll back newly created overrides instead of leaving incomplete records.

💾 Build file (258c143).

zackkatz added 2 commits July 22, 2026 20:33
Verified each of Codex's adversarial-review findings against source before
writing anything (per the review request); all 5 confirmed real, no false
positives:

1. Template_Manager::update_template() checks wp_insert_post()'s error but
   silently discards both wp_set_object_terms() calls that follow it
   (class-template-manager.php:316, :320). A pre_insert_term failure (or any
   other wp_set_object_terms() failure) leaves a published wp_template/
   wp_template_part row with no wp_theme term -- orphaned: get_block_templates()
   can never find it again, yet it lingers in the database with whatever
   content the call went on to write, and the caller is told success:true.

2. Pattern_Manager::create_pattern() checks `'' === $title` on the RAW
   value before sanitize_text_field() runs (class-pattern-manager.php:747-748,
   applied only later at :817). A whitespace-only or pure-markup title
   (e.g. "<script></script>") passes the raw check and collapses to an
   empty post_title at insert time.

3. create_pattern() always returns a `core/block` synced-reference
   snippet (class-pattern-manager.php:858), even for sync_status:"unsynced" --
   following it would re-link content the caller explicitly asked to keep
   non-propagating.

4. Tool_Executor::execute_list_block_types() never reads `include_supports`
   from $input, so ability callers always get stripped block types
   regardless of what they pass (class-tool-executor.php:150-159).

5. Tool_Executor::execute_list_patterns() never reads `category` and never
   forwards the REST response's `categories` vocabulary, so ability
   results diverge from REST/npm-MCP (class-tool-executor.php:191-225).

New tests/Abilities/ToolExecutorParityAuditTest.php: a structural audit --
every property a manifest tool declares in its input_schema must appear,
verbatim, in that tool's Tool_Executor::execute_<name>() method body.
Running it against the unmodified codebase caught findings #4 and #5
exactly, plus a third divergence it correctly surfaced and I investigated
separately: update_block's `block_name` is declared but never referenced.
That one is NOT a wiring gap -- block_name selects which npm-MCP-server-side
enricher (src/enrichers.ts) to run entirely client-side before only the
already-enriched attributes/innerHTML are sent over the wire; the REST
endpoint never accepts a block_name parameter, so Tool_Executor has nothing
to forward it to. Documented as a real, separate, pre-existing gap (the
Abilities path gets no automatic computed-field derivation the way npm-MCP
callers do) via an explicit, commented exemption rather than silently
dropped or expanded into a PHP-side enrichment port.

New tests/Abilities/ListToolsAbilityParityTest.php: behavioral proof for
findings #4/#5 specifically (the structural audit proves the argument name
is *referenced*; these prove it changes the actual response).

tests/REST/CreatePatternTest.php gains title-sanitization tests (#2, plus a
control case: real text with incidental whitespace must still succeed) and
reference/insert_hint tests (#3, plus a control case pinning the synced
response shape is unchanged).

tests/Templates/TemplateManagerWriteTest.php gains two rollback tests (#1):
a pre_insert_term filter forces wp_theme term assignment to fail for a
wp_template write, and a second test isolates the wp_template_part_area
assignment specifically (by letting wp_theme succeed and only failing the
area term) so both checks this issue asks for are independently proven.

Confirmed red (full suite, not just the new files):

  $ composer test
  Tests: 1425, Assertions: 18456, Failures: 8.

  1) CreatePatternTest::test_whitespace_only_title_is_rejected
  2) CreatePatternTest::test_markup_only_title_that_sanitizes_to_empty_is_rejected
  3) CreatePatternTest::test_unsynced_pattern_does_not_return_synced_reference
  4) ListToolsAbilityParityTest::test_list_block_types_ability_forwards_include_supports
  5) ListToolsAbilityParityTest::test_list_patterns_ability_forwards_category_filter_and_includes_categories
  6) ToolExecutorParityAuditTest::test_every_manifest_input_property_is_referenced_by_its_tool_executor_method
  7) TemplateManagerWriteTest::test_update_template_rolls_back_new_override_when_wp_theme_term_assignment_fails
  8) TemplateManagerWriteTest::test_update_template_rolls_back_new_override_when_area_term_assignment_fails

  $ npm test
  Test Files  55 passed (55)  -- no TS-side change needed for red yet;
  types/tool description updates for finding #3 land in the green commit.

Claude-Session: https://claude.ai/code/session_013YcSbKroBJjPanX3okQrT3
Codex review of the merged range 602ae77...b089815 flagged five
findings; all five verified genuine against source and fixed here:

1. Template_Manager::update_template() now checks the WP_Error return
   of both wp_set_object_terms() calls when creating a new override,
   deleting the freshly-inserted post and returning the error on
   failure instead of leaving an untraceable orphan post behind.

2. Pattern_Manager::create_pattern() now sanitizes `title` before the
   emptiness check, so a whitespace- or markup-only title that
   collapses to '' under sanitize_text_field() is rejected instead of
   silently creating a nameless pattern.

3. create_pattern()'s response now omits `reference` for an unsynced
   pattern (core/block is a live, propagating reference — wrong for a
   one-off) and instead returns `insert_hint` pointing callers at
   insert_pattern's synced:false path. TS types (CreatePatternResponse)
   and the create_pattern tool description are updated to match; the
   synced case is unchanged (backward compatible).

4. Tool_Executor::execute_list_block_types() now forwards
   `include_supports` on the Abilities/MCP-Adapter path, matching REST
   and the npm MCP server.

5. Tool_Executor::execute_list_patterns() now forwards `category` and
   includes `categories` in its response, matching REST and the npm
   MCP server.

Findings 4 and 5 are the same REST-vs-Abilities parity bug class as
prior fixes; ToolExecutorParityAuditTest (added in the red commit)
statically compares every manifest-declared input property against
each tool's execute_*() method body via Reflection, so a newly added
argument that isn't forwarded on the Abilities path now fails CI
instead of shipping silently. It documents two narrow, deliberate
exemptions: tools that forward $input wholesale, and update_block's
`block_name` (a client-side-only enrichment selector with no REST
equivalent — a real, separate gap, not this bug class).

All five findings are pinned by tests (see the red commit); none
required a manual-only verification note.

Claude-Session: https://claude.ai/code/session_013YcSbKroBJjPanX3okQrT3
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The changes update create_pattern response shapes and title sanitization, extend block and pattern listing parameters, add executor parity coverage, and roll back newly created template overrides when taxonomy assignment fails.

Changes

Pattern response handling

Layer / File(s) Summary
Conditional pattern responses
src/types.ts, src/tools/patterns.ts, wordpress-plugin/gk-block-mcp/includes/class-pattern-manager.php, wordpress-plugin/gk-block-mcp/assets/mcp-server/index.cjs, wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json, wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php
Titles are sanitized before validation and storage. Synced patterns return reference; unsynced patterns omit it and return an insert_hint. Tests cover title validation and both response shapes.

Tool listing parity

Layer / File(s) Summary
Listing filters and parity validation
wordpress-plugin/gk-block-mcp/includes/class-tool-executor.php, wordpress-plugin/gk-block-mcp/tests/Abilities/*
Block type listing forwards include_supports; pattern listing forwards category and returns categories. Ability tests and a manifest/executor audit validate the updated forwarding behavior.

Template override rollback

Layer / File(s) Summary
Taxonomy failure cleanup
wordpress-plugin/gk-block-mcp/includes/class-template-manager.php, wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php
Newly created template overrides are deleted when required taxonomy term assignment returns an error, with regression tests for templates and template parts.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the PR, but it is too generic and doesn’t describe the actual fixes in the changeset. Use a more specific title such as the main fixes: template rollback, pattern title sanitization, synced/unsynced pattern responses, and list tool forwarding.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 93.75% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/codex-review-findings

Comment @coderabbitai help to get the list of available commands.

@zackkatz
zackkatz merged commit 69c993c into develop Jul 23, 2026
8 of 9 checks passed
@zackkatz
zackkatz deleted the fix/codex-review-findings branch July 23, 2026 00:46

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

🧹 Nitpick comments (3)
wordpress-plugin/gk-block-mcp/includes/class-tool-executor.php (1)

197-197: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Name the checks before these ternaries.

Inline isset()/type checks in ternaries conflict with the plugin conditional-check convention.

Proposed cleanup
+		$has_category = isset( $input['category'] );
 		$params = array(
-			'category'  => isset( $input['category'] ) ? (string) $input['category'] : null,
+			'category'  => $has_category ? (string) $input['category'] : null,
 		);

+		$has_categories = isset( $data['categories'] ) && is_array( $data['categories'] );
-		$categories = isset( $data['categories'] ) && is_array( $data['categories'] ) ? $data['categories'] : array();
+		$categories = $has_categories ? $data['categories'] : array();

As per coding guidelines, “Assign checks to named variables before if, while, or ternary conditionals instead of inlining function calls or compound expressions.”

Also applies to: 217-217

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/includes/class-tool-executor.php` at line 197,
In the tool input construction around the category and corresponding line 217
field, assign each inline isset/type-check condition to a clearly named boolean
variable before the ternary expressions. Update the ternaries to use those named
checks while preserving the existing cast and null fallback behavior.

Source: Coding guidelines

wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php (1)

2-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace review history and off-tree references with local behavioral contracts.

  • wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php#L2-L9: describe the parity behavior under test; remove Codex-review history and meta-test commentary.
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php#L20-L24: state the Abilities bootstrap precondition locally; remove the cross-test docblock reference.
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ToolExecutorParityAuditTest.php#L2-L9: describe the audit’s current invariant without review-finding history.
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ToolExecutorParityAuditTest.php#L20-L29: document the wholesale-forwarding exemption as a contract; remove verification-process instructions.
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ToolExecutorParityAuditTest.php#L45-L58: retain only the PHP-side exemption contract; remove src/enrichers.ts pointers and future-feature discussion.
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ToolExecutorParityAuditTest.php#L96-L101: state why missing executor methods are skipped without referring to another test.

As per coding guidelines, comments must document “current behavior and hard contracts only” and omit “history, journal entries, off-tree specification pointers, and future-architecture speculation.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php`
around lines 2 - 9, Replace review history, meta-test commentary, off-tree
references, verification instructions, and future-architecture speculation in
ListToolsAbilityParityTest.php (lines 2-9 and 20-24) and
ToolExecutorParityAuditTest.php (lines 2-9, 20-29, 45-58, and 96-101) with
concise comments describing only the local behavioral parity contract, Abilities
bootstrap precondition, wholesale-forwarding and PHP-side exemptions, and why
missing executor methods are skipped.

Source: Coding guidelines

wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json (1)

1122-1122: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Clarify whether the unsynced insertion hint is partial.

The manifest and regression test describe only pattern_id and synced:false, but insert_pattern requires post_id. Make the hint explicitly partial and require callers to add post_id, or expose a complete executable parameter set.

  • wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json#L1122-L1122: clarify the missing destination parameter in the public description.
  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L244-L269: align the assertion and documentation with the partial-hint contract.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json` at line
1122, Clarify the unsynced pattern contract in
wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json: describe
insert_hint as a partial parameter set and explicitly require callers to add
post_id before invoking insert_pattern. In
wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php lines 244-269,
update the regression assertion and accompanying documentation to verify and
describe that post_id is intentionally omitted and must be supplied by the
caller.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wordpress-plugin/gk-block-mcp/includes/class-template-manager.php`:
- Around line 319-329: In the template creation flow, assign the results of both
is_wp_error() checks for $theme_term and $area_term to clearly named boolean
variables before their respective if statements, then branch on those variables
while preserving the existing cleanup and return behavior.
- Around line 318-329: Update the rollback paths in the template creation flow
around the wp_theme and wp_template_part_area taxonomy assignments to check the
result of wp_delete_post( $post_id, true ). If cleanup fails, return a dedicated
WP_Error with HTTP status 500; otherwise preserve returning the original
taxonomy/write error. Apply this consistently to every rollback deletion path in
the surrounding logic.

In `@wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php`:
- Around line 168-175: Remove the “Codex review” attribution and review-history
wording from both documentation blocks in
wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L168-L175 and
`#L223-L229`. Retain only the current contracts: sanitize the title before
checking emptiness at the first site, and document the synced/unsynced response
behavior at the second site.
- Around line 211-220: Update
test_title_with_real_text_and_surrounding_whitespace_is_accepted in
CreatePatternTest so the title input contains real markup, such as emphasized
text, alongside surrounding whitespace. Adjust the expected response title
assertion to match the sanitized result, preserving coverage for successful
markup handling rather than whitespace-only input.

In `@wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php`:
- Around line 394-408: Replace the historical “Codex review” comment near the
term-assignment tests with a concise present-tense contract describing that
failed required taxonomy assignment returns WP_Error and deletes the newly
created override. Remove review-tool attribution, defect history, and
explanatory implementation narrative while preserving the test’s behavioral
requirement.

---

Nitpick comments:
In `@wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json`:
- Line 1122: Clarify the unsynced pattern contract in
wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json: describe
insert_hint as a partial parameter set and explicitly require callers to add
post_id before invoking insert_pattern. In
wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php lines 244-269,
update the regression assertion and accompanying documentation to verify and
describe that post_id is intentionally omitted and must be supplied by the
caller.

In `@wordpress-plugin/gk-block-mcp/includes/class-tool-executor.php`:
- Line 197: In the tool input construction around the category and corresponding
line 217 field, assign each inline isset/type-check condition to a clearly named
boolean variable before the ternary expressions. Update the ternaries to use
those named checks while preserving the existing cast and null fallback
behavior.

In
`@wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php`:
- Around line 2-9: Replace review history, meta-test commentary, off-tree
references, verification instructions, and future-architecture speculation in
ListToolsAbilityParityTest.php (lines 2-9 and 20-24) and
ToolExecutorParityAuditTest.php (lines 2-9, 20-29, 45-58, and 96-101) with
concise comments describing only the local behavioral parity contract, Abilities
bootstrap precondition, wholesale-forwarding and PHP-side exemptions, and why
missing executor methods are skipped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2ace5a0b-0025-439e-aa36-c36fe79e3fde

📥 Commits

Reviewing files that changed from the base of the PR and between b089815 and 258c143.

📒 Files selected for processing (11)
  • src/tools/patterns.ts
  • src/types.ts
  • wordpress-plugin/gk-block-mcp/assets/mcp-server/index.cjs
  • wordpress-plugin/gk-block-mcp/includes/abilities/tools.manifest.json
  • wordpress-plugin/gk-block-mcp/includes/class-pattern-manager.php
  • wordpress-plugin/gk-block-mcp/includes/class-template-manager.php
  • wordpress-plugin/gk-block-mcp/includes/class-tool-executor.php
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ListToolsAbilityParityTest.php
  • wordpress-plugin/gk-block-mcp/tests/Abilities/ToolExecutorParityAuditTest.php
  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php
  • wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php

Comment on lines +318 to +329
$theme_term = wp_set_object_terms( $post_id, get_stylesheet(), 'wp_theme' );
if ( is_wp_error( $theme_term ) ) {
wp_delete_post( $post_id, true );
return $theme_term;
}

if ( 'wp_template_part' === $type ) {
$area = ! empty( $template->area ) ? (string) $template->area : WP_TEMPLATE_PART_AREA_UNCATEGORIZED;
wp_set_object_terms( $post_id, _filter_block_template_part_area( $area ), 'wp_template_part_area' );
$area = ! empty( $template->area ) ? (string) $template->area : WP_TEMPLATE_PART_AREA_UNCATEGORIZED;
$area_term = wp_set_object_terms( $post_id, _filter_block_template_part_area( $area ), 'wp_template_part_area' );
if ( is_wp_error( $area_term ) ) {
wp_delete_post( $post_id, true );
return $area_term;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the target file and inspect the relevant range.
ast-grep outline wordpress-plugin/gk-block-mcp/includes/class-template-manager.php --view expanded || true
wc -l wordpress-plugin/gk-block-mcp/includes/class-template-manager.php
sed -n '280,360p' wordpress-plugin/gk-block-mcp/includes/class-template-manager.php

# Find surrounding error-handling patterns in the plugin.
rg -n "wp_delete_post\\(|new WP_Error|handle_error\\(|is_wp_error\\(" wordpress-plugin/gk-block-mcp/includes -g '*.php'

Repository: GravityKit/block-mcp

Length of output: 20636


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect WordPress deletion semantics from the codebase if any wrapper exists.
rg -n "wp_delete_post\\(" wordpress-plugin -g '*.php'
rg -n "cleanup-specific 500|WP_Error|500" wordpress-plugin/gk-block-mcp/includes -g '*.php'

Repository: GravityKit/block-mcp

Length of output: 50376


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the specific section around the reported lines.
sed -n '300,350p' wordpress-plugin/gk-block-mcp/includes/class-template-manager.php

Repository: GravityKit/block-mcp

Length of output: 1822


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the matching cleanup pattern in post-manager and the template write test.
sed -n '236,262p' wordpress-plugin/gk-block-mcp/includes/class-post-manager.php
sed -n '390,430p' wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php

Repository: GravityKit/block-mcp

Length of output: 2903


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '400,440p' wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php
sed -n '404,422p' wordpress-plugin/gk-block-mcp/includes/class-template-manager.php

Repository: GravityKit/block-mcp

Length of output: 2234


Handle rollback deletion failures. In every rollback path here, check wp_delete_post() and return a dedicated 500 if cleanup fails; otherwise the original taxonomy/write error is returned while the published override can remain orphaned.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/includes/class-template-manager.php` around
lines 318 - 329, Update the rollback paths in the template creation flow around
the wp_theme and wp_template_part_area taxonomy assignments to check the result
of wp_delete_post( $post_id, true ). If cleanup fails, return a dedicated
WP_Error with HTTP status 500; otherwise preserve returning the original
taxonomy/write error. Apply this consistently to every rollback deletion path in
the surrounding logic.

Comment on lines +319 to +329
if ( is_wp_error( $theme_term ) ) {
wp_delete_post( $post_id, true );
return $theme_term;
}

if ( 'wp_template_part' === $type ) {
$area = ! empty( $template->area ) ? (string) $template->area : WP_TEMPLATE_PART_AREA_UNCATEGORIZED;
wp_set_object_terms( $post_id, _filter_block_template_part_area( $area ), 'wp_template_part_area' );
$area = ! empty( $template->area ) ? (string) $template->area : WP_TEMPLATE_PART_AREA_UNCATEGORIZED;
$area_term = wp_set_object_terms( $post_id, _filter_block_template_part_area( $area ), 'wp_template_part_area' );
if ( is_wp_error( $area_term ) ) {
wp_delete_post( $post_id, true );
return $area_term;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Name the error predicates before branching.

Extract each is_wp_error() result into a named boolean before its if statement.

As per coding guidelines, “Assign checks to named variables before if, while, or ternary conditionals instead of inlining function calls or compound expressions.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/includes/class-template-manager.php` around
lines 319 - 329, In the template creation flow, assign the results of both
is_wp_error() checks for $theme_term and $area_term to clearly named boolean
variables before their respective if statements, then branch on those variables
while preserving the existing cleanup and return behavior.

Source: Coding guidelines

Comment on lines +168 to +175
// ── Codex review: title sanitized before, not after, the empty check ──

/**
* A whitespace-only title passes the raw non-empty-string check but
* `sanitize_text_field()` trims it to '' when building post_title,
* silently creating a nameless pattern. The emptiness check must run
* against the sanitized value.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove review-tool history from test documentation.

Both ranges include Codex review attribution. Comments should describe only the current sanitization and response-shape contracts.

  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L168-L175: remove the review-history banner and retain the sanitize-before-empty-check contract.
  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L223-L229: remove the review-history banner and retain the synced/unsynced response contract.

As per coding guidelines, comments/docblocks must document current behavior and hard contracts and omit review-tool attributions and historical journals.

📍 Affects 1 file
  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L168-L175 (this comment)
  • wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L223-L229
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php` around lines
168 - 175, Remove the “Codex review” attribution and review-history wording from
both documentation blocks in
wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php#L168-L175 and
`#L223-L229`. Retain only the current contracts: sanitize the title before
checking emptiness at the first site, and document the synced/unsynced response
behavior at the second site.

Source: Coding guidelines

Comment on lines +211 to +220
public function test_title_with_real_text_and_surrounding_whitespace_is_accepted() {
$response = $this->create_pattern(
array(
'title' => ' Real Title ',
'content' => '<!-- wp:paragraph --><p>hi</p><!-- /wp:paragraph -->',
)
);

$this->assertInstanceOf( \WP_REST_Response::class, $response );
$this->assertSame( 'Real Title', $response->get_data()['title'] );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exercise the markup-preserving success case.

The docblock claims whitespace/markup coverage, but the input only contains whitespace. Use real text wrapped in markup, such as <em>Real Title</em>, and assert the sanitized result so over-aggressive sanitization remains covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/tests/REST/CreatePatternTest.php` around lines
211 - 220, Update
test_title_with_real_text_and_surrounding_whitespace_is_accepted in
CreatePatternTest so the title input contains real markup, such as emphasized
text, alongside surrounding whitespace. Adjust the expected response title
assertion to match the sanitized result, preserving coverage for successful
markup handling rather than whitespace-only input.

Comment on lines +394 to +408
// ── Codex review: term-assignment failure must not orphan the override ─

/**
* `wp_insert_post()`'s error is checked, but the two `wp_set_object_terms()`
* calls that follow it were not — a taxonomy failure (e.g. a
* `pre_insert_term` filter rejecting the `wp_theme` term) left a
* published `wp_template`/`wp_template_part` row with no `wp_theme`
* term, so `get_block_templates()` could never find it again
* (`get_template()` would keep resolving the theme file), yet the
* orphaned post — and whatever content the call went on to write into it
* — stayed in the database with `success: true` reported to the caller.
* The fix must check both term-assignment calls and roll back
* (`wp_delete_post()`) the freshly-created override on failure, exactly
* like the existing legacy-block-rejection rollback.
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove review history from the test comments.

“Codex review” and the defect history violate the comment policy. Keep a short present-tense contract, e.g. “A failed required taxonomy assignment returns WP_Error and removes the new override.”

As per coding guidelines, comments must “document current behavior and hard contracts” and omit “review-tool attributions” and “historical journals.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wordpress-plugin/gk-block-mcp/tests/Templates/TemplateManagerWriteTest.php`
around lines 394 - 408, Replace the historical “Codex review” comment near the
term-assignment tests with a concise present-tense contract describing that
failed required taxonomy assignment returns WP_Error and deletes the newly
created override. Remove review-tool attribution, defect history, and
explanatory implementation narrative while preserving the test’s behavioral
requirement.

Source: Coding guidelines

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.

1 participant