Skip to content

Release: merge develop into main#34

Open
zackkatz wants to merge 15 commits into
mainfrom
develop
Open

Release: merge develop into main#34
zackkatz wants to merge 15 commits into
mainfrom
develop

Conversation

@zackkatz

@zackkatz zackkatz commented Jun 17, 2026

Copy link
Copy Markdown
Member

Promotes the queued develop work to main for the next release. Opened per the branch → develop → main flow.

Included now

Rolling in before merge

Two PRs are in review against develop and will appear here automatically once merged:

Before merging

  • Bump the version: turn = develop = into = X.Y.Z on <date> = in readme.txt, and update the plugin Version/Stable tag (and the server package.json if releasing it together).

Hold until #32 and #33 land in develop.

💾 Build file (ce7f2e8).

Summary by CodeRabbit

Release Notes

  • New Features

    • Added "Add row" buttons to preference tables for clearer namespace and mapping management.
  • Bug Fixes

    • Fixed nested block deletion correctness.
    • Restored Yoast tool compatibility for Gemini-based assistants.
  • Improvements

    • Enhanced settings table persistence and merging with defaults.
    • Added validation warning when namespace scores lack a name.
    • Updated bundled dependencies for security advisories.
  • Chores

    • Bumped to version 2.0.3.

zackkatz and others added 10 commits June 15, 2026 13:48
phpstan-bootstrap.php (placeholder constants for static analysis) was shipping
in the build: the .distignore *.dist glob catches phpstan.neon.dist and
phpcs.xml.dist, but this file ends in .php so it slipped through. It is dev-only
(referenced solely by phpstan.neon.dist's bootstrapFiles, never loaded at
runtime), so list it explicitly. .distignore is the single source of truth for
both the CircleCI and GitHub Actions packaging paths, so this fixes both.
CircleCI's build_package_release owns releases (build + sign + announce to the
Release Manager, which updates EDD), as it did through 2.0.0. The GitHub Actions
'Create tag + release for the new version' step (added after 2.0.1) created the
v{version} tag/release on the main merge, racing CircleCI's create_release —
the collision aborted CircleCI before its announce, so EDD never updated (2.0.1
and 2.0.2 both stuck until pushed manually).

Restore build-plugin-zip.yml to its v2.0.1 shape: it still builds the zip,
uploads the artifact, updates the rolling 'latest' prerelease, and keeps the
'Tagged release' backstop that fires AFTER CircleCI pushes the v* tag (no race).
Only the v{version}-on-merge creation is removed, so CircleCI is the sole
creator of the version tag + release and its announce runs every release.
… null]

The yoast_update_seo / yoast_bulk_update_seo input schema advertised
noindex as type: ['boolean', 'null']. Anthropic's tool-schema validator
rejects a 'null' member in a JSON Schema type array and returns a 400 for
the ENTIRE tools/list request, which takes every tool on the server
offline for Claude / Anthropic API clients, not just this field.

Schema now advertises type: 'boolean'. The runtime handler is unchanged
and still accepts an explicit null (tri-state true/false/null is preserved;
covered by the existing 'noindex tri-state: null is preserved' test). Added
a regression test asserting no field in the shared Yoast property set uses a
type array containing 'null'.

dist/ is a build artifact (npm run build / prepare) and is intentionally
left out of this PR.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…undle; credit contributor

Builds on @dallinchase's noindex scalar-type change. Verified the type-array
rejection reproduces on Google Gemini's functionDeclarations (HTTP 400 "Proto
field is not repeating, cannot start list"), NOT the Anthropic API (accepts
["boolean","null"] on stable 2023-06-01 + tool betas) or OpenAI (strict and
non-strict). Re-attributes the field description to Gemini and corrects the
tri-state wording: null resets to the post-type default (delete_post_meta),
omit leaves the current value unchanged.

Also:
- Regenerate the git-tracked embedded bundle (CI verifies it byte-for-byte via
  .github/workflows/tests.yml + tests/packaging.test.ts).
- Fix a TS2352 in the regression test (cast through unknown; tsconfig.build.json
  excludes tests so CI missed it, but tsc -p tsconfig.json flags it).
- Credit Dallin Chase in the changelog for the original fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm audit: 0 vulnerabilities (clears the open Dependabot alerts).

Runtime (bundled into the shipped MCP server):
- axios ^1.7.9 -> ^1.16.0 (resolves several high/medium advisories)
- form-data and qs/hono refresh to patched versions via the lockfile

Dev:
- esbuild ^0.27.3 -> ^0.28.1; vitest ^3.2.4 -> ^3.2.6 (critical)
- vite refreshes to a patched 7.3.5 via the lockfile
- overrides: { esbuild: "$esbuild" } forces vite's nested esbuild to the patched
  0.28.1, clearing the dev-server advisories without a major vitest bump

Bumps the MCP server (package.json) 2.0.1 -> 2.0.2 — 2.0.1 is already published,
and npm-publish.yml only ships when the version is new, so without the bump the
patched bundle would never reach npx users. The server versions independently of
the plugin.

Rebuilt the bundle (handshake version + patched axios/form-data) on top of the
current develop tree, so the committed embedded copy keeps the Yoast/Gemini fix
and gains the dependency patches. Verified: npm run build, tsc, the full vitest
suite (724 tests), and npm audit (0) all pass. Changelog entry added under
= develop =.
The Settings → Block MCP block-score and replacement tables stored a lossy
subset of preferences, and the first-ever save lost everything:

- Render and sanitize read the raw stored option instead of layering over
  Preferences::get_defaults(), so the shipped defaults vanished from the tables
  once any custom entry was stored (the runtime kept merging them, so the UI
  contradicted enforcement).
- The sanitize callback only understood the form's indexed-row shape. Core
  double-sanitizes an option on its first write — update_option() delegates to
  add_option(), which sanitizes again — so the second pass received the
  callback's own {namespace_scores, replacement_map} output, found no rows, and
  collapsed the option to []. The first save silently wiped everything.

Render now uses the merged Preferences::get_preferences() view; sanitize layers
posted rows over the defaults and is idempotent (it accepts its own canonical
output, so a second pass is a no-op). The racy type-to-grow auto-row is replaced
with an explicit "Add row" button, and a score entered without a block-family
name now warns on save instead of being dropped silently.
# Conflicts:
#	wordpress-plugin/gk-block-mcp/readme.txt
…Add row

PHPUnit (tests/Connect/SettingsPagePreferencesTest.php): render and sanitize
layer over the shipped defaults; sanitize is idempotent; the first save of a
brand-new option survives core's update_option()->add_option() double-sanitize
via the real mechanism; a scored row with no name surfaces a settings error
while a fully blank trailing row does not.

Adds a committed admin-UI regression e2e harness (tests/e2e/, npm run test:e2e)
that drives the live settings page: a namespace added via the Add row button
persists across save, and a score with no name warns instead of vanishing.
- e2e: replace waitForLoadState('networkidle') (discouraged by Playwright) with
  deterministic waits — wait for the settings-updated redirect before reloading,
  and let the visible-warning assertion auto-wait across the form-submit
  navigation.
- readme: move the "Add row" entry from Fixed to a new Improved section (a UI
  enhancement, not a bug fix).
- tests: rewrite docblocks to present-tense contract language, dropping the
  "before the fix" history per the comment guideline.

Skipped CodeRabbit's "@SInCE on new members": no PHPUnit test method in the
suite carries @SInCE — it's a production-API convention, not a test one.
chore(deps): patch npm security advisories (clears all 20 Dependabot alerts)
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR delivers the 2.0.3 plugin release: sanitize_preferences() is rewritten to layer posted values over shipped defaults and warn on incomplete rows; preference table UIs switch from trigger-based auto-grow to explicit "Add row" buttons; PHP unit tests and Playwright E2E tests are added to cover both paths. The Yoast noindex schema type is narrowed from a boolean/null union to a single boolean. CI auto-tagging on main is removed, dependencies are bumped, and the bundled MCP server gains escapeHeaderParam for multipart header sanitization.

Changes

Settings Page Overhaul

Layer / File(s) Summary
sanitize_preferences() rewrite and render_page data source
wordpress-plugin/gk-block-mcp/includes/class-settings-page.php
sanitize_preferences() initializes a dropped-row counter, handles both row-indexed and canonical input shapes, layers results over Preferences::get_defaults(), and emits a settings error for scored rows with a blank name. render_page() switches both policy tables to read from Preferences::get_preferences().
UI: explicit "Add row" buttons replacing trigger-field auto-grow
wordpress-plugin/gk-block-mcp/includes/class-settings-page.php
Removes data-row-trigger attributes from namespace and replacement-map table inputs, adds explicit "Add row" buttons after each table, and rewrites the inline JS to clone/reindex the last row, announce via live region, and focus the first new input.
PHP unit tests for Settings_Page preferences
wordpress-plugin/gk-block-mcp/tests/Connect/SettingsPagePreferencesTest.php
Adds SettingsPagePreferencesTest covering render-path defaults visibility, sanitizer layering, override semantics, blank-name warning, empty-row suppression, idempotency, and first-save persistence through WordPress core's double-sanitize.
Playwright E2E config and settings-preferences tests
tests/e2e/playwright.config.ts, tests/e2e/settings-preferences.e2e.ts, package.json, .gitignore
Adds a Playwright config scoped to *.e2e.ts (Chromium, single worker, 60s timeout). Adds two E2E tests: "Add row" persists a new namespace+score through save/reload; submitting a blank-name scored row renders a warning. Adds test:e2e script and ignores .playwright-artifacts/.

Yoast noindex Schema Fix

Layer / File(s) Summary
noindex schema type and regression test
src/tools/yoast.ts, src/__tests__/tools/yoast/yoast_update_seo.test.ts, wordpress-plugin/gk-block-mcp/assets/mcp-server/index.cjs
YOAST_FIELD_PROPERTIES changes noindex type from ["boolean","null"] to "boolean" with an updated description. A regression test asserts no tool input property uses a null-union type. The bundled index.cjs reflects the same change.

CI Simplification, Dependency Updates, and Docs

Layer / File(s) Summary
CI workflow: remove auto-tagging on main push
.github/workflows/build-plugin-zip.yml
Removes the block that read the plugin version from headers/changelog and called gh release create on main pushes, leaving only the rolling latest release for main and the tagged-release step for refs/tags/v*.
Bundled MCP server: escapeHeaderParam and error handling
wordpress-plugin/gk-block-mcp/assets/mcp-server/index.cjs
__commonJS wraps the factory in a try/catch. escapeHeaderParam sanitizes CR, LF, and double quotes and is applied to multipart Content-Disposition name and filename values. Embedded package.json dependencies are updated to match the root package.json.
Dependency bumps, version increment, and .distignore
package.json, wordpress-plugin/gk-block-mcp/gk-block-mcp.php, wordpress-plugin/gk-block-mcp/readme.txt, wordpress-plugin/gk-block-mcp/.distignore
package.json bumps version to 2.0.2, upgrades axios, esbuild, and vitest, and adds an esbuild overrides pin. Plugin PHP and readme.txt are bumped to 2.0.3. .distignore excludes phpstan-bootstrap.php.
Documentation and changelog updates
AGENTS.md, wordpress-plugin/AGENTS.md, wordpress-plugin/gk-block-mcp/readme.txt
AGENTS.md and wordpress-plugin/AGENTS.md remove Upgrade Notice references and update @since and versioning guidance. readme.txt adds the 2.0.3 changelog entry.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • GravityKit/block-mcp#26: This PR directly reverses that PR's addition of auto-version-detection and gh release create logic in .github/workflows/build-plugin-zip.yml.
  • GravityKit/block-mcp#30: Both PRs modify the Yoast noindex JSON schema to advertise a single boolean type and add or verify the regression test enforcing that contract.
  • GravityKit/block-mcp#33: Both PRs implement the same settings-page fixes — sanitize_preferences() default layering, idempotent first-save, explicit "Add row" UI, and the accompanying PHP unit and E2E test coverage.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Release: merge develop into main' is vague and generic, using 'merge' and 'develop/main' terminology that doesn't convey the specific content, version bump, or key improvements of this 2.0.3 release. Replace with a more specific, descriptive title that highlights the main change, such as 'Release 2.0.3: Fix Yoast schema and update dependencies' or similar.
✅ Passed checks (4 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 84.21% 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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 develop

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

zackkatz added 5 commits June 16, 2026 23:03
fix(settings): keep block-preference defaults and persist the first save
Stamps the queued develop work as 2.0.3: turns the = develop = changelog into
= 2.0.3 on June 17, 2026 = with a release summary, and bumps the plugin Version
header, GK_BLOCK_MCP_VERSION, and readme Stable tag from 2.0.2 to 2.0.3.

The MCP server (package.json) stays 2.0.2 — it versions independently and has no
new change this release; the 2.0.2 server publishes when this reaches main.
…nt attribution

Addresses CodeRabbit on PR #34:
- AGENTS.md: drop "== Upgrade Notice ==" from the version-bump list (four places,
  not five). Releases now source notes from the Changelog entry (per the earlier
  ci(release) change), and the plugin updates through Foundation, so the section
  is never surfaced. Scope @SInCE to shipped public members, with test files
  explicitly exempt — the whole suite leaves them un-annotated.
- Correct the yoast_update_seo test comment to attribute the null-in-type-array
  rejection to AI clients like Gemini, matching the implementation comment.

Skips CodeRabbit's "add Upgrade Notice" and "add @SInCE to the test class" — both
contradict the established practice the guidance now documents.
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.

2 participants