$npx -y skills add amElnagdy/guard-skills --skill woo-guardReview generated or changed WooCommerce code — extensions, payment and shipping integrations, checkout customizations, and order/product logic — before it ships. Best used reactively after an agent writes, edits, or reviews code touching WooCommerce APIs: wc_get_order, wc_get_ord
| 1 | # Woo Guard |
| 2 | |
| 3 | You are reviewing generated or changed WooCommerce code before it ships. Apply the rules below as a guard pass after the first implementation pass. WooCommerce is a moving platform — order storage changed engines, checkout changed frameworks — and code written from memory targets the WooCommerce of three years ago. With money on the line, "works on my demo store" is not a standard. |
| 4 | |
| 5 | These rules exist because AI agents produce WooCommerce code with systematic failures: order meta read through `get_post_meta()` (broken on HPOS stores), products updated by direct meta writes that skip lookup tables and hooks, checkout validated only in JavaScript, prices computed in floats, and `woocommerce_*` hooks registered before confirming WooCommerce is active. |
| 6 | |
| 7 | ## How to use this skill |
| 8 | |
| 9 | **Guard-pass mode** (recommended): after WooCommerce code has been generated or edited, apply the rules to the diff or target files, then run the self-check before delivery. |
| 10 | |
| 11 | **Live mode** (explicit): when the user invokes this skill before writing WooCommerce code, apply the same rules while writing, then run the self-check before delivery. |
| 12 | |
| 13 | **Review mode** (the user asks you to review or audit WooCommerce code): walk [references/review-checklist.md](references/review-checklist.md) and produce a structured findings report. Do not edit code in review mode unless asked. |
| 14 | |
| 15 | **Security floor** — these hold in all WooCommerce code, at maximum severity, because money is on the line: |
| 16 | |
| 17 | - Escape all output with the context-correct `esc_*` function. |
| 18 | - `wp_unslash()` then sanitize all request data before it touches logic. |
| 19 | - Capability check plus nonce on every state change. |
| 20 | - `$wpdb->prepare()` for every query containing a variable. |
| 21 | |
| 22 | If wp-guard is installed, run it alongside for the full WordPress layer. |
| 23 | |
| 24 | ## Adapt to the project first |
| 25 | |
| 26 | 1. Read the project's agent instructions and the extension's declared WooCommerce version range. Project conventions win on conflict. |
| 27 | 2. Determine the order storage mode this code must support: HPOS, legacy posts, or both (the default assumption is both). |
| 28 | 3. Determine the checkout in play: Blocks/Store API, legacy shortcode checkout, or both. Hooks for one do not fire in the other. |
| 29 | 4. Check whether WooCommerce activity is guarded: feature checks or `class_exists( 'WooCommerce' )` before any `wc_*` call or `woocommerce_*` hook. |
| 30 | |
| 31 | ## The Rules |
| 32 | |
| 33 | ### Order and product data — must fix |
| 34 | |
| 35 | 1. **Orders are not posts.** Access orders only through the CRUD API: `wc_get_order()`, `wc_get_orders()`, `$order->get_meta()`, `$order->update_meta_data()` + `$order->save()`. Forbidden on order data: `get_post_meta()`, `update_post_meta()`, `WP_Query`/`get_posts()` with `post_type => shop_order`, and direct `$wpdb` joins on postmeta. These work on legacy stores and silently break on HPOS stores. Details: [references/hpos-and-crud.md](references/hpos-and-crud.md). |
| 36 | |
| 37 | 2. **CRUD objects, getters/setters, then save.** Products, customers, and coupons go through their CRUD objects (`wc_get_product()`, setters, `->save()`). Direct meta writes skip lookup-table sync, skip the hooks other extensions rely on, and skip cache invalidation. Stock changes go through `wc_update_product_stock()` semantics; order state changes through `$order->update_status()` — which fire the emails and hooks the store expects. |
| 38 | |
| 39 | 3. **Declare feature compatibility.** Any extension touching orders declares HPOS compatibility (`FeaturesUtil::declare_compatibility( 'custom_order_tables', … )`); any extension touching checkout declares `cart_checkout_blocks` compatibility (or incompatibility, honestly). A missing declaration shows every store owner a warning banner with your plugin's name on it. |
| 40 | |
| 41 | ### Checkout and money — must fix |
| 42 | |
| 43 | 4. **Checkout validation is server-side.** Validate at `woocommerce_checkout_process` (legacy) or through Store API extension schemas (Blocks). JavaScript validation is UX, never security. Know which checkout t |