Skip to content

Content Guidelines AI: restore compatibility with the Gutenberg 23.6 Guidelines page#50658

Draft
aagam-shah wants to merge 2 commits into
trunkfrom
fix/content-guidelines-ai-gb-store-removal
Draft

Content Guidelines AI: restore compatibility with the Gutenberg 23.6 Guidelines page#50658
aagam-shah wants to merge 2 commits into
trunkfrom
fix/content-guidelines-ai-gb-store-removal

Conversation

@aagam-shah

@aagam-shah aagam-shah commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Fixes N/A — compatibility fix for a Gutenberg refactor.

Proposed changes

Gutenberg 23.6 dissolved the Guidelines singleton into per-scope wp_knowledge rows (WordPress/gutenberg#79263) and deleted the core/guidelines data store. Five files in the Content Guidelines AI integration selected or dispatched on that store, so on the new Guidelines page every injected component crashes its React root and none of the AI UI renders. The page now keeps section drafts in React component state only, so the DOM textareas are the one place drafts are observable from our bundle.

  • Add lib/drafts.js: snapshot-style draft reads (readSectionDraft, readAllSectionDrafts, areAllSectionDraftsEmpty, getSectionTextarea, getBlockModalTextarea) plus a subscription layer fed by a capture-phase input listener and a MutationObserver that re-checks the watched values on DOM churn — catching value writes Gutenberg makes without input events (e.g. Clear guidelines resetting the form), while skipping notifications when no draft actually changed.
  • Add hooks/use-drafts.js (useSectionDraft, useAllSectionsEmpty, useBlockDraft) built on useSyncExternalStore, replacing the getGuideline/getBlockGuideline selectors for the Generate ↔ Improve labels.
  • Accepting a section suggestion now writes the textarea through the native value setter + input event so Gutenberg's own onChange updates its draft state (same pattern the block modal already used); the user then saves via Gutenberg's Save button as before. If the textarea can't be found, the suggestion is kept instead of being silently discarded.
  • Generate handlers snapshot the drafts at click time (render-time hook values only drive labels), and setGuideline/STORE_NAME usage is removed everywhere.
  • Behavior note: the block modal's Generate/Improve label now keys off the live modal textarea (which opens prefilled with the saved guideline) rather than the persisted row — consistent with the sections and with what was already sent to the AI endpoint as existing content.
  • Performance: both draft-change sources (document input listener, MutationObserver) funnel through a single value-compare gate, so unrelated typing and non-draft DOM churn cause no subscriber fan-out; the label hooks return booleans so buttons re-render only at the empty/non-empty boundary. Measured on the wp-env page: ~39µs per value-changing keystroke for the whole bundle path, ~14µs for unrelated-field keystrokes, ~11µs per DOM-churn observer check (Gutenberg's own form re-render, ~1.5ms/keystroke, dominates and is unchanged).
  • Add jest coverage for the new layer (23 tests) and register _inc/content-guidelines-ai/ in the client jest config roots.

Works on both the old and new Guidelines pages: the DOM anchors used here (.guidelines__list-item[data-slug], form/textarea structure, .block-guideline-modal) are unchanged between the pre- and post-refactor Gutenberg, so rollout order doesn't matter.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No new tracking. Existing jetpack_content_guidelines_* events unchanged; the action (generate/improve) property for block-modal events is now derived from the live modal textarea instead of the deleted store selector.

Testing instructions

Unit tests:

  • cd projects/plugins/jetpack && pnpm exec jest --config=tests/jest.config.client.js _inc/content-guidelines-ai

Manual (needs a Gutenberg checkout at 23.6+, e.g. trunk, in wp-env, since wpcom still runs the old page):

  • In the Gutenberg repo: npm run wp-env start, enable the "Guidelines" experiment (Settings → Gutenberg → Experiments), then open Settings → Guidelines and confirm wp.data.select( 'core/guidelines' ) is undefined in the console — this is the environment where trunk Jetpack crashes.
  • Load this branch's built content-guidelines-ai bundle on that page (jetpack-beta on a test site once wpcom ships the new GB, or a dev bundle in the console).
  • Confirm: the header Generate guidelines button, per-section Generate buttons, and "Read more" link all render.
  • Type into a section textarea → its button and the header button flip to "Improve guidelines"; clear the text → back to "Generate guidelines".
  • Click a section's Generate button → shimmer, then a diff view with Accept/Dismiss. Accept → the text lands in the textarea, Gutenberg's "Save guidelines" button enables, and saving persists the row ("Guidelines saved." snackbar).
  • Click Clear guidelines and confirm → after the snackbar, the buttons read "Generate guidelines" again (this exercises the no-input-event reactivity path).
  • Open the Blocks section → Add guidelines → pick a block → Generate/Accept inside the modal writes the modal textarea; Save persists.

🤖 Generated with Claude Code

Gutenberg 23.6 dissolved the Guidelines singleton into per-scope
wp_knowledge rows (GB#79263) and deleted the core/guidelines data store
the integration consumed for section drafts. Every injected component
that selected or dispatched on that store now crashes its React root, so
none of the AI generate/accept UI renders on the new Guidelines page.

Since the page keeps its drafts in React component state only, the DOM
textareas are the one observable source: a new lib/drafts.js snapshots
them and notifies subscribers from a capture-phase input listener plus a
MutationObserver that re-checks the watched values on DOM churn (catching
value writes Gutenberg makes without input events, e.g. Clear
guidelines). Accepting a section suggestion now writes the textarea
through the native setter so Gutenberg's own onChange keeps its state in
sync, and keeps the suggestion when the textarea is missing rather than
silently dropping accepted text. Generate handlers snapshot drafts at
click time; render-time hook values only drive the labels.

The block modal's Generate/Improve label now keys off the live modal
textarea (which opens prefilled with the saved guideline) instead of the
deleted getBlockGuideline selector — matching what was already sent to
the AI endpoint as existing content.

Verified end-to-end against the new page on a local Gutenberg wp-env:
injection, label reactivity, generate/diff/accept, Gutenberg save and
clear, and the block modal flows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the fix/content-guidelines-ai-gb-store-removal branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack fix/content-guidelines-ai-gb-store-removal

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions Bot added [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Tests] Includes Tests labels Jul 20, 2026
@github-actions

github-actions Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR restores the Jetpack Content Guidelines AI UI on the Gutenberg 23.6+ Guidelines page by removing reliance on the deleted core/guidelines data store and instead reading/updating guideline drafts directly from the page’s DOM textareas (with reactive subscriptions for button labels and click-time snapshotting for API calls).

Changes:

  • Introduce a DOM draft tracking layer (lib/drafts.js) and reactive hooks (hooks/use-drafts.js) built on useSyncExternalStore to keep “Generate/Improve” labels in sync with live textarea content.
  • Update generate/accept flows to snapshot draft content at click time and, on accept, write through the native textarea setter + bubbling input event so Gutenberg’s internal state stays consistent.
  • Add Jest coverage for the new draft layer and include _inc/content-guidelines-ai/ in the client Jest config roots/coverage.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
File Description
projects/plugins/jetpack/tests/jest.config.client.js Expands Jest roots and coverage collection to include Content Guidelines AI client code.
projects/plugins/jetpack/changelog/fix-content-guidelines-ai-gb-store-removal Adds a compat changelog entry describing the Gutenberg 23.6 compatibility fix.
projects/plugins/jetpack/_inc/content-guidelines-ai/lib/drafts.js Implements DOM-based draft reads plus input/MO-driven subscription notifications.
projects/plugins/jetpack/_inc/content-guidelines-ai/hooks/use-drafts.js Adds useSyncExternalStore hooks to consume the DOM draft layer in UI components.
projects/plugins/jetpack/_inc/content-guidelines-ai/lib/dom.js Adds section-suggestion acceptance that writes via native setter + input event.
projects/plugins/jetpack/_inc/content-guidelines-ai/lib/inject.js Starts draft tracking on injection and centralizes modal textarea lookup.
projects/plugins/jetpack/_inc/content-guidelines-ai/hooks/use-generate-all.js Removes store reads and snapshots all section drafts from DOM at click time.
projects/plugins/jetpack/_inc/content-guidelines-ai/constants.js Removes the core/guidelines store constant.
projects/plugins/jetpack/_inc/content-guidelines-ai/components/suggestion-actions.jsx Accept now writes into the textarea (DOM) rather than dispatching to a removed store.
projects/plugins/jetpack/_inc/content-guidelines-ai/components/suggest-all-button.jsx Button label now reflects DOM draft emptiness via useAllSectionsEmpty.
projects/plugins/jetpack/_inc/content-guidelines-ai/components/section-generate-button.jsx Uses useSectionDraft for labels and snapshots DOM draft on click for requests/tracks.
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-buttons.jsx Uses modal textarea draft for labels and click-time snapshots, matching new page behavior.
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-actions.jsx Uses shared modal textarea getter for consistent DOM access.
projects/plugins/jetpack/_inc/content-guidelines-ai/test/fixtures/index.js Adds DOM fixtures to mimic the Guidelines page and block modal structures in tests.
projects/plugins/jetpack/_inc/content-guidelines-ai/test/drafts.test.js Adds unit tests for draft reads, subscriptions, input events, and mutation-driven reactivity.
projects/plugins/jetpack/_inc/content-guidelines-ai/test/use-drafts.test.jsx Adds hook-level tests verifying reactive draft reads for sections and the block modal.
projects/plugins/jetpack/_inc/content-guidelines-ai/test/dom.test.js Adds tests for native-setter textarea writes and section acceptance behavior.

@jp-launch-control

Copy link
Copy Markdown

Code Coverage Summary

20 files are newly checked for coverage. Only the first 5 are listed here.

File Coverage
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-actions.jsx 0/30 (0.00%) 💔
projects/plugins/jetpack/_inc/content-guidelines-ai/components/block-suggestion-buttons.jsx 0/35 (0.00%) 💔
projects/plugins/jetpack/_inc/content-guidelines-ai/components/diff-view.jsx 0/14 (0.00%) 💔
projects/plugins/jetpack/_inc/content-guidelines-ai/components/empty-state-banner.jsx 0/12 (0.00%) 💔
projects/plugins/jetpack/_inc/content-guidelines-ai/components/read-more-link.jsx 0/4 (0.00%) 💔

Full summary · PHP report · JS report

If appropriate, add one of these labels to override the failing coverage check: Covered by non-unit tests Use to ignore the Code coverage requirement check when E2Es or other non-unit tests cover the code Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage.

Performance pass over the draft tracker:

- Funnel the input listener and the MutationObserver through one
  checkAndNotify that compares the watched values before notifying, so
  typing in unrelated fields (block combobox, admin search) and
  non-draft DOM churn cost a single ~11us read pass with no subscriber
  fan-out.
- Compare the watched values element-wise instead of joining them into
  one string; guideline text can reach 5000 chars per section, and the
  join copied up to ~25KB per check.
- Make the label hooks return booleans (useSectionHasDraft,
  useBlockHasDraft, useAllSectionsEmpty was already boolean): the
  consumers only choose Generate-vs-Improve labels, so components now
  re-render at the empty/non-empty boundary instead of every keystroke.

Measured on the wp-env Guidelines page: a value-changing keystroke costs
the bundle ~39us end-to-end (listener + compare + boolean snapshots);
unrelated-field keystrokes ~14us with zero fan-out; observer checks on
DOM churn ~11us. Gutenberg's own controlled-form re-render (~1.5ms per
keystroke) dominates and is unchanged by this bundle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Status] In Progress [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants