Commit 668724a11cb for woocommerce

commit 668724a11cbf71f5003f1e5caa8ed29145a29b66
Author: Raluca Stan <ralucastn@gmail.com>
Date:   Tue Jul 21 15:40:13 2026 -0400

    docs: audit and tighten AI agent instruction files

    Trim duplicated general guidance and fix stale references across the
    CLAUDE.md/AGENTS.md instruction files, keeping only what is specific to
    this repo.

    - AGENTS.md: add a block.json field-types note pointing at the Gutenberg
      Block Metadata reference, and flag that style/editorStyle/script/
      viewScript are string | string[] so readers must handle both shapes.
    - client/admin/CLAUDE.md: replace the generic WAI-ARIA how-to (semantic
      HTML, ARIA patterns, examples, checklist, resources) with a pointer to
      the WordPress Accessibility Handbook and WAI-ARIA Authoring Practices,
      keeping only the WooCommerce-specific testing-query guidance.
    - src/Internal/Admin/Settings/CLAUDE.md: correct the WooPaymentsRestController
      path (now under PaymentsProviders/WooPayments/) and drop the stale
      "Known Issues Fixed" table.

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

diff --git a/AGENTS.md b/AGENTS.md
index 4e99d8a30b8..b90a849050e 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -199,6 +199,10 @@ Do not add `default` values to block attributes in `block.json`.
 - Defaults can create subtle conflicts with `theme.json`, block supports, editor controls, deprecations, and migrations.
 - During implementation or review, flag any newly inserted `default` in `block.json`.

+### `block.json` Field Types
+
+Consult the [Gutenberg Block Metadata reference](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/) as the source of truth for `block.json` field types. Several fields (`style`, `editorStyle`, `script`, `viewScript`) accept `string | string[]`, so code that reads them must handle both shapes — don't assume a string.
+
 ## Interactivity API Stores

 Most WooCommerce Interactivity API stores are **private by design**. Exception: the `woocommerce/product-filters` store is public for Product Filters inner-block extensibility.
diff --git a/plugins/woocommerce/client/admin/CLAUDE.md b/plugins/woocommerce/client/admin/CLAUDE.md
index 5e5297b68f0..582558f306b 100644
--- a/plugins/woocommerce/client/admin/CLAUDE.md
+++ b/plugins/woocommerce/client/admin/CLAUDE.md
@@ -316,205 +316,15 @@ When rendering disabled/unsupported features, pass minimal props to prevent inad

 ## Accessibility (WAI-ARIA)

-### Critical Rules for Accessible Components
+All UI components must follow WAI-ARIA guidelines. This section captures only the
+WooCommerce-specific guidance; for the general rules (semantic HTML first, ARIA
+patterns for dialogs/forms/status, focus management, jest-axe) follow the
+[WordPress Accessibility Handbook](https://make.wordpress.org/accessibility/handbook/)
+and the [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/).

-All UI components must follow WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) guidelines to ensure the admin interface is usable by everyone, including users with disabilities.
-
-### Semantic HTML First
-
-Always use semantic HTML before adding ARIA attributes:
-
-```typescript
-// GOOD - Semantic HTML
-<button onClick={handleClick}>Save</button>
-
-// BAD - Non-semantic with ARIA
-<div role="button" onClick={handleClick}>Save</div>
-
-// GOOD - Use <label> for form fields
-<label htmlFor="gateway-name">Gateway Name</label>
-<input id="gateway-name" type="text" />
-
-// BAD - Using aria-label only
-<input type="text" aria-label="Gateway Name" />
-```
-
-### Required ARIA Patterns
-
-**Interactive Elements:**
-
-- All buttons must have accessible names (visible text or `aria-label`)
-- Icon-only buttons MUST have `aria-label`
-- Disabled elements should have `aria-disabled="true"`
-
-```typescript
-// Icon button
-<button aria-label="Close dialog">
-  <CloseIcon />
-</button>
-
-// Button with loading state
-<button disabled={isLoading} aria-disabled={isLoading}>
-  {isLoading ? 'Loading...' : 'Submit'}
-</button>
-```
-
-**Status and State:**
-
-- Use `aria-live` for dynamic content updates
-- Status badges should use `role="status"` or `aria-label`
-- Loading states need `aria-busy="true"`
-
-```typescript
-// Status badge
-<span className="status-badge" role="status" aria-label="Payment gateway is active">
-  Active
-</span>
-
-// Live region for notifications
-<div aria-live="polite" aria-atomic="true">
-  {notificationMessage}
-</div>
-
-// Loading state
-<div aria-busy={isLoading} aria-label="Loading payment methods">
-  {content}
-</div>
-```
-
-**Landmarks and Navigation:**
-
-- Use semantic landmarks: `<nav>`, `<main>`, `<aside>`, `<header>`, `<footer>`
-- Add `aria-label` to multiple landmarks of same type
-- Ensure proper heading hierarchy (`<h1>` → `<h2>` → `<h3>`)
-
-```typescript
-// Multiple navigation regions
-<nav aria-label="Main navigation">...</nav>
-<nav aria-label="Settings tabs">...</nav>
-
-// Main content area
-<main aria-label="Payment settings">...</main>
-```
-
-**Forms and Inputs:**
-
-- Associate labels with inputs using `htmlFor`/`id`
-- Use `aria-describedby` for help text and errors
-- Mark required fields with `aria-required="true"` or `required`
-
-```typescript
-// Form field with help text
-<label htmlFor="api-key">API Key</label>
-<input
-  id="api-key"
-  type="text"
-  required
-  aria-describedby="api-key-help"
-  aria-invalid={hasError}
-/>
-<span id="api-key-help">Enter your payment gateway API key</span>
-{hasError && (
-  <span id="api-key-error" role="alert">
-    Invalid API key format
-  </span>
-)}
-```
-
-**Dialogs and Modals:**
-
-- Use `role="dialog"` or `role="alertdialog"`
-- Add `aria-modal="true"` for modal dialogs
-- Include `aria-labelledby` pointing to title
-- Trap focus within modal
-
-```typescript
-<div
-  role="dialog"
-  aria-modal="true"
-  aria-labelledby="dialog-title"
-  aria-describedby="dialog-description"
->
-  <h2 id="dialog-title">Confirm Setup</h2>
-  <p id="dialog-description">Are you sure you want to enable this gateway?</p>
-  <button onClick={handleConfirm}>Confirm</button>
-  <button onClick={handleCancel}>Cancel</button>
-</div>
-```
-
-### Testing Accessibility
-
-**Use React Testing Library's accessibility queries (preferred order):**
-
-1. `getByRole` - Best for interactive elements
-2. `getByLabelText` - Best for form inputs
-3. `getByText` - For visible text content
-4. `getByTitle` - For elements with title attribute
-
-```typescript
-import { render, screen } from '@testing-library/react';
-
-describe('PaymentGatewayItem', () => {
-  it('has accessible status badge', () => {
-    render(<PaymentGatewayItem status="active" />);
-
-    // Query by role
-    const badge = screen.getByRole('status', { name: /active/i });
-    expect(badge).toBeInTheDocument();
-  });
-
-  it('has accessible setup button', () => {
-    render(<PaymentGatewayItem />);
-
-    // Button with accessible name
-    const button = screen.getByRole('button', { name: /complete setup/i });
-    expect(button).toBeInTheDocument();
-  });
-
-  it('has properly labeled form inputs', () => {
-    render(<GatewaySettings />);
-
-    // Query by label
-    const apiKeyInput = screen.getByLabelText(/api key/i);
-    expect(apiKeyInput).toBeRequired();
-  });
-});
-```
-
-**Test keyboard navigation:**
-
-```typescript
-import userEvent from '@testing-library/user-event';
-
-it('supports keyboard navigation', async () => {
-  const user = userEvent.setup();
-  render(<PaymentGatewayList />);
-
-  // Tab through interactive elements
-  await user.tab();
-  expect(screen.getByRole('button', { name: /setup/i })).toHaveFocus();
-
-  // Activate with keyboard
-  await user.keyboard('{Enter}');
-  expect(mockOnSetup).toHaveBeenCalled();
-});
-```
-
-**Automated accessibility testing:**
-
-Consider using `jest-axe` for automated checks:
-
-```typescript
-import { axe, toHaveNoViolations } from 'jest-axe';
-
-expect.extend(toHaveNoViolations);
-
-it('has no accessibility violations', async () => {
-  const { container } = render(<PaymentGatewayItem />);
-  const results = await axe(container);
-  expect(results).toHaveNoViolations();
-});
-```
+**Test with React Testing Library's accessibility queries**, in priority order:
+`getByRole` (interactive elements) → `getByLabelText` (form inputs) → `getByText`
+→ `getByTitle`. Prefer these over `data-testid` so tests assert the accessible name.

 ### Common WooCommerce Admin Patterns

@@ -536,27 +346,6 @@ import { Button, Modal, Notice } from '@wordpress/components';
 <Notice status="error">Failed to connect</Notice>
 ```

-### Checklist for New Components
-
-Before marking a component as complete:
-
-- [ ] Uses semantic HTML elements where possible
-- [ ] All interactive elements are keyboard accessible (Tab, Enter, Space)
-- [ ] All images/icons have alternative text or `aria-label`
-- [ ] Form inputs have associated labels
-- [ ] Error messages are announced (use `role="alert"` or `aria-live`)
-- [ ] Focus is managed properly (dialogs, dynamic content)
-- [ ] Color is not the only way to convey information
-- [ ] Component passes `jest-axe` checks (if configured)
-- [ ] Tested with screen reader queries (`getByRole`, `getByLabelText`)
-
-### Resources
-
-- **WAI-ARIA Authoring Practices**: <https://www.w3.org/WAI/ARIA/apg/>
-- **React Testing Library**: <https://testing-library.com/docs/queries/about/#priority>
-- **WordPress Accessibility Handbook**: <https://make.wordpress.org/accessibility/handbook/>
-- **axe DevTools**: Browser extension for accessibility testing
-
 ### Common Violations to Avoid

 | Issue | Wrong | Correct |
diff --git a/plugins/woocommerce/src/Internal/Admin/Settings/CLAUDE.md b/plugins/woocommerce/src/Internal/Admin/Settings/CLAUDE.md
index 3f4f277802f..b817022ccd4 100644
--- a/plugins/woocommerce/src/Internal/Admin/Settings/CLAUDE.md
+++ b/plugins/woocommerce/src/Internal/Admin/Settings/CLAUDE.md
@@ -27,11 +27,12 @@

 ```text
 Settings/
-|-- PaymentsRestController.php       # Main REST endpoint
-|-- WooPaymentsRestController.php    # WooPayments endpoints
-|-- Payments.php                     # Business logic
-|-- PaymentsProviders.php            # Provider aggregation
-`-- Utils.php                        # Utilities
+|-- PaymentsRestController.php                          # Main REST endpoint
+|-- Payments.php                                        # Business logic
+|-- PaymentsProviders.php                               # Provider aggregation
+|-- Utils.php                                           # Utilities
+`-- PaymentsProviders/WooPayments/
+    `-- WooPaymentsRestController.php                   # WooPayments endpoints
 ```

 ## Critical Patterns
@@ -77,15 +78,6 @@ $schema = array(
 );
 ```

-## Known Issues Fixed
-
-| File | Line | Issue | Fix |
-|------|------|-------|-----|
-| PaymentsRestController.php | 885-895 | `messages` uses `items` | Changed to `additionalProperties` |
-| WooPaymentsRestController.php | 1066-1076 | `messages` uses `items` | Changed to `additionalProperties` |
-| WooPaymentsRestController.php | 1107 | `type: enum` | Changed to `type: string` |
-| WooPaymentsRestController.php | 1246 | `type: enum` | Changed to `type: string` |
-
 ## Known Issues (Incomplete Schemas)

 ### onboarding.state Schema (PaymentsRestController.php:880-884)
@@ -189,7 +181,7 @@ array(
 | File | Endpoint | Key Methods |
 |------|----------|-------------|
 | PaymentsRestController.php | `/wc-admin/settings/payments/*` | `get_providers()`, `set_country()`, `update_providers_order()` |
-| WooPaymentsRestController.php | `/wc-admin/settings/payments/providers/woopayments/*` | `get_onboarding_details()` |
+| PaymentsProviders/WooPayments/WooPaymentsRestController.php | `/wc-admin/settings/payments/providers/woopayments/*` | `get_onboarding_details()` |
 | Payments.php | N/A (business logic) | `get_payment_providers()`, `get_payment_extension_suggestions()` |

 ## Linting