Skip to content

Steer agent to use Jetpack Forms instead of raw HTML forms - #3351

Merged
youknowriad merged 6 commits into
trunkfrom
claude/sleepy-spence-18348f
May 6, 2026
Merged

Steer agent to use Jetpack Forms instead of raw HTML forms#3351
youknowriad merged 6 commits into
trunkfrom
claude/sleepy-spence-18348f

Conversation

@youknowriad

@youknowriad youknowriad commented May 6, 2026

Copy link
Copy Markdown
Contributor

Related issues

  • Related to agent site-building improvements

How AI was used in this PR

This PR was generated with Claude Code. The architecture and guidance text were written by AI and reviewed for correctness.

Proposed Changes

Introduces a plugin-recommendations.ts registry so the agent knows which plugins to reach for rather than hand-rolling raw HTML. Each entry in the registry declares the plugin, its blocks, guidance text for the system prompt, and optional HTML patterns to flag in the block content policy. Adding new rules in the future (e.g. WooCommerce) requires only one object in the array — no other files change.

This PR ships one rule: Jetpack Forms.

When the agent is asked for any form (contact, feedback, newsletter, survey), it now:

  1. Installs Jetpack if not already active
  2. Builds the form with jetpack/contact-form and jetpack/field-* blocks using the exact composite markup Jetpack generates in the editor
  3. Gets a targeted error from the block content policy if it falls back to a raw <form> element in a core/html block

Files changed:

  • apps/cli/ai/plugin-recommendations.ts (new) — the recommendation registry
  • apps/cli/ai/block-content-policy.ts<form> HTML no longer silently passes; the policy loop iterates PLUGIN_RECOMMENDATIONS so any rule with htmlPatterns is enforced automatically
  • apps/cli/ai/system-prompt.ts — local content guidelines now append all guidance strings from the registry

Testing Instructions

  • Ask the agent to "add a contact form" on a local site → it should install Jetpack and produce jetpack/contact-form block markup, not a <form> element
  • Place a <!-- wp:html -->…<form>…</form>…<!-- /wp:html --> block in content and run validate_blocks → the policy should return the Jetpack-specific error message (not the generic "use core blocks" message)

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?
Introduces a generic plugin-recommendations architecture so the agent knows
which plugins to reach for instead of hand-rolling HTML. Adding a new rule
requires only one object in the PLUGIN_RECOMMENDATIONS array — the system
prompt and block content policy both pick it up automatically.

First two rules:
- Jetpack Forms: agent installs Jetpack and uses jetpack/contact-form +
  jetpack/field-* blocks instead of raw <form> HTML. The block content
  policy now flags <form> HTML with a targeted error pointing to Jetpack.
- WooCommerce: agent installs WooCommerce and uses woocommerce/* blocks for
  any shop, product listing, cart, or checkout request.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
youknowriad and others added 4 commits May 6, 2026 06:06
- Update the form-markup test to assert the Jetpack-specific error message
  instead of expecting an empty array (the old allowed-exception behavior)
- Replace non-existent woocommerce/product-grid with woocommerce/product-collection
  in the recommendation blocks list and guidance text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Current Jetpack releases create core/button for form submission rather than
the legacy jetpack/button block. Update both the blocks list and the example
markup in the Jetpack Forms recommendation to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous example used self-closing field blocks, but real Jetpack forms
use composite field blocks where each field wraps jetpack/label + jetpack/input
children. Updates the recommendation to reflect this:

- Replace the simplified self-closing example with the actual markup Jetpack
  inserts when clicking "contact form" in the block editor
- Add jetpack/label and jetpack/input to the blocks list
- Explain the inner-block structure in the field-type description

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scope this PR to Jetpack Forms only. WooCommerce can land as a follow-up
once the plugin recommendation architecture is reviewed and merged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@youknowriad youknowriad changed the title Add plugin recommendation rules (Jetpack Forms, WooCommerce) May 6, 2026
@wpmobilebot

wpmobilebot commented May 6, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing f78e842 vs trunk

app-size

Metric trunk f78e842 Diff Change
App Size (Mac) 1409.73 MB 1454.06 MB +44.33 MB 🔴 3.1%

site-editor

Metric trunk f78e842 Diff Change
load 1515 ms 1500 ms 15 ms ⚪ 0.0%

site-startup

Metric trunk f78e842 Diff Change
siteCreation 8088 ms 8078 ms 10 ms ⚪ 0.0%
siteStartup 4920 ms 4950 ms +30 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@lezama

lezama commented May 6, 2026

Copy link
Copy Markdown
Contributor

Pushed f78e8423 on top of this branch.

Problem

Tested this branch end-to-end against a fresh local site by running the agent with "add a contact form". The agent followed the guidance perfectly — installed Jetpack, generated the prescribed jetpack/contact-form markup, validate_blocks returned 2/2 valid — but the rendered frontend had no <form>, <input>, or <label> elements. Just empty <div>s where the fields should be.

Root cause: in Jetpack 15.7, wp plugin install jetpack --activate does not activate the contact-form module by default. Without it, none of the jetpack/* blocks register, so <!-- wp:jetpack/contact-form --> etc. parse as known but produce no inner HTML on the frontend (the <div class="wp-block-jetpack-contact-form"> is the static save() output, but <form> and the field children come from server-side render_callback — which never runs without the module).

The failure is silent: validate_blocks parses the markup successfully (the blocks are well-formed), but the user gets an empty form on the live site.

Reproduction (before the fix)

$ wp plugin install jetpack --activate
$ wp jetpack module list | grep contact-form
contact-form    Inactive

$ wp eval 'echo count(array_filter(array_keys(\WP_Block_Type_Registry::get_instance()->get_all_registered()), fn($n) => str_starts_with($n, "jetpack/")));'
0

# After adding a jetpack/contact-form block to a page:
$ curl -s http://localhost:8889/ | grep -c '<form'
0
$ curl -s http://localhost:8889/ | grep -c '<input'
0

I confirmed empirically that only the contact-form module is needed (not blocks — that's a separate module for unrelated Jetpack blocks like maps/cover, has no effect on Forms).

Fix in this commit

Updates the Jetpack Forms guidance to instruct the agent to activate the module after installing the plugin:

wp_cli plugin install jetpack --activate
wp_cli jetpack module activate contact-form

Re-ran the agent end-to-end with the new build — it followed the new instruction, and the rendered form now has 1 <form>, 6 <input>s, 3 <label>s, 1 <textarea>, and 1 submit button on the live page.

Disclosure

Fix and this comment were drafted by Claude after I confirmed the reproduction and fix manually.

@youknowriad

Copy link
Copy Markdown
Contributor Author

Ok this is working well :)

@youknowriad
youknowriad merged commit 333c917 into trunk May 6, 2026
10 checks passed
@youknowriad
youknowriad deleted the claude/sleepy-spence-18348f branch May 6, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants