---
name: wordpress-theme-development
description: "WordPress theme development workflow covering theme architecture, template hierarchy, custom post types, block editor support, responsive design, and WordPress 7.0 features: DataViews, Pattern Editing, Navigation Overlays, and admin refresh."
category: granular-workflow-bundle
risk: safe
source: personal
date_added: "2026-02-27"
---

# WordPress Theme Development Workflow

## Overview

Specialized workflow for creating custom WordPress themes from scratch, including modern block editor (Gutenberg) support, template hierarchy, responsive design, and WordPress 7.0 enhancements.

## WordPress 7.0 Theme Features

1. **Admin Refresh**
   - New default color scheme
   - View transitions between admin screens
   - Modern typography and spacing

2. **Pattern Editing**
   - ContentOnly mode defaults for unsynced patterns
   - `disableContentOnlyForUnsyncedPatterns` setting
   - Per-block instance custom CSS

3. **Navigation Overlays**
   - Customizable navigation overlays
   - Improved mobile navigation

4. **New Blocks**
   - Icon block
   - Breadcrumbs block with filters
   - Responsive grid block

5. **Theme.json Enhancements**
   - Pseudo-element support
   - Block-defined feature selectors honored
   - Enhanced custom CSS

6. **Iframed Editor**
   - Block API v3+ enables iframed post editor
   - Full enforcement in 7.1, opt-in in 7.0

## When to Use This Workflow

Use this workflow when:
- Creating custom WordPress themes
- Converting designs to WordPress themes
- Adding block editor support
- Implementing custom post types
- Building child themes
- Implementing WordPress 7.0 design features

## Workflow Phases

### Phase 1: Theme Setup

#### Skills to Invoke
- `app-builder` - Project scaffolding
- `frontend-developer` - Frontend development

#### Actions
1. Create theme directory structure
2. Set up style.css with theme header
3. Create functions.php
4. Configure theme support
5. Set up enqueue scripts/styles

#### WordPress 7.0 Theme Header
```css
/*
Theme Name: My Custom Theme
Theme URI: https://example.com
Author: Developer Name
Author URI: https://example.com
Description: A WordPress 7.0 compatible theme with modern design
Version: 1.0.0
Requires at least: 6.0
Requires PHP: 7.4
License: GNU General Public License v2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-custom-theme
Tags: block-patterns, block-styles, editor-style, wide-blocks
*/
```

#### Copy-Paste Prompts
```
Use @app-builder to scaffold a new WordPress theme project
```

### Phase 2: Template Hierarchy

#### Skills to Invoke
- `frontend-developer` - Template development

#### Actions
1. Create index.php (fallback template)
2. Implement header.php and footer.php
3. Create single.php for posts
4. Create page.php for pages
5. Add archive.php for archives
6. Implement search.php and 404.php

#### WordPress 7.0 Template Considerations
- Test with iframed editor
- Verify view transitions work
- Check new admin color scheme compatibility

#### Copy-Paste Prompts
```
Use @frontend-developer to create WordPress template files
```

### Phase 3: Theme Functions

#### Skills to Invoke
- `backend-dev-guidelines` - Backend patterns

#### Actions
1. Register navigation menus
2. Add theme support (thumbnails, RSS, etc.)
3. Register widget areas
4. Create custom template tags
5. Implement helper functions

#### WordPress 7.0 theme.json Configuration
```json
{
  "$schema": "https://schemas.wp.org/trunk/theme.json",
  "version": 3,
  "settings": {
    "appearanceTools": true,
    "layout": {
      "contentSize": "1200px",
      "wideSize": "1400px"
    },
    "background": {
      "backgroundImage": true
    },
    "typography": {
      "fontFamilies": true,
      "fontSizes": true
    },
    "spacing": {
      "margin": true,
      "padding": true
    },
    "blocks": {
      "core/heading": {
        "typography": {
          "fontSizes": ["24px", "32px", "48px"]
        }
      }
    }
  },
  "styles": {
    "color": {
      "background": "#ffffff",
      "text": "#1a1a1a"
    },
    "elements": {
      "link": {
        "color": {
          "text": "#0066cc"
        }
      }
    }
  },
  "customTemplates": [
    {
      "name": "page-home",
      "title": "Homepage",
      "postTypes": ["page"]
    }
  ],
  "templateParts": [
    {
      "name": "header",
      "title": "Header",
      "area": "header"
    }
  ]
}
```

#### Copy-Paste Prompts
```
Use @backend-dev-guidelines to create theme functions
```

### Phase 4: Custom Post Types

#### Skills to Invoke
- `wordpress-penetration-testing` - WordPress patterns

#### Actions
1. Register custom post types
2. Create custom taxonomies
3. Add custom meta boxes
4. Implement custom fields
5. Create archive templates

#### RTC-Compatible CPT Registration
```php
register_post_type('portfolio', [
    'labels' => [
        'name' => __('Portfolio', 'my-theme'),
        'singular_name' => __('Portfolio Item', 'my-theme')
    ],
    'public' => true,
    'has_archive' => true,
    'show_in_rest' => true,  // Enable for RTC
    'supports' => ['title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'],
    'menu_icon' => 'dashicons-portfolio',
]);

// Register meta for collaboration
register_post_meta('portfolio', 'client_name', [
    'type' => 'string',
    'single' => true,
    'show_in_rest' => true,
    'sanitize_callback' => 'sanitize_text_field',
]);
```

#### Copy-Paste Prompts
```
Use @wordpress-penetration-testing to understand WordPress CPT patterns
```

### Phase 5: Block Editor Support

#### Skills to Invoke
- `frontend-developer` - Block development

#### Actions
1. Enable block editor support
2. Register custom blocks
3. Create block styles
4. Add block patterns
5. Configure block templates

#### WordPress 7.0 Block Features
- Block API v3 is reference model
- PHP-only block registration
- Per-instance custom CSS
- Block visibility controls (viewport-based)

#### Block Pattern with ContentOnly (WP 7.0)
```json
{
    "name": "my-theme/hero-section",
    "title": "Hero Section",
    "contentOnly": true,
    "content": [
        {
            "name": "core/cover",
            "attributes": {
                "url": "{{hero_image}}",
                "overlay": "black",
                "dimRatio": 50
            },
            "innerBlocks": [
                {
                    "name": "core/heading",
                    "attributes": {
                        "level": 1,
                        "textAlign": "center",
                        "content": "{{hero_title}}"
                    }
                },
                {
                    "name": "core/paragraph",
                    "attributes": {
                        "align": "center",
                        "content": "{{hero_description}}"
                    }
                }
            ]
        }
    ]
}
```

#### Navigation Overlay Template Part
```php
// template-parts/header-overlay.php
?>
<nav class="header-navigation-overlay" aria-label="<?php esc_attr_e('Overlay Menu', 'my-theme'); ?>">
    <button class="overlay-close" aria-label="<?php esc_attr_e('Close menu', 'my-theme'); ?>">
        <span class="close-icon" aria-hidden="true">
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <line x1="18" y1="6" x2="6" y2="18"></line>
                <line x1="6" y1="6" x2="18" y2="18"></line>
            </svg>
        </span>
    </button>
    <?php
    wp_nav_menu([
        'theme_location' => 'primary',
        'container' => false,
        'menu_class' => 'overlay-menu',
        'fallback_cb' => false,
    ]);
    ?>
</nav>
```

#### Copy-Paste Prompts
```
Use @frontend-developer to create custom Gutenberg blocks
```

### Phase 6: Styling and Design

#### Skills to Invoke
- `frontend-design` - UI design
- `tailwind-patterns` - Tailwind CSS

#### Actions
1. Implement responsive design
2. Add CSS framework or custom styles
3. Create design system
4. Implement theme customizer
5. Add accessibility features

#### WordPress 7.0 Admin Refresh Considerations
```css
/* Support new admin color scheme */
@media (prefers-color-scheme: dark) {
    :root {
        --admin-color: modern;
    }
}

/* View transitions */
.wp-admin {
    view-transition-name: none;
}

body {
    view-transition-name: page;
}
```

#### CSS Custom Properties (WP 7.0)
```css
:root {
    /* New DataViews colors */
    --wp-dataviews-color-background: #ffffff;
    --wp-dataviews-color-border: #e0e0e0;

    /* Navigation overlay */
    --wp-overlay-menu-background: #1a1a1a;
    --wp-overlay-menu-text: #ffffff;
}
```

#### Copy-Paste Prompts
```
Use @frontend-design to create responsive theme design
```

### Phase 7: WordPress 7.0 Features Integration

#### Breadcrumbs Block Support
```php
// Add breadcrumb filters for custom post types
add_filter('wp_breadcrumb_args', function($args) {
    $args['separator'] = '<span class="breadcrumb-separator"> / </span>';
    $args['before'] = '<nav class="breadcrumb" aria-label="Breadcrumb">';
    $args['after'] = '</nav>';
    return $args;
});

// Add custom breadcrumb trail for CPT
add_action('breadcrumb_items', function($trail, $crumbs) {
    if (is_singular('portfolio')) {
        $portfolio_page = get_page_by_path('portfolio');
        if ($portfolio_page) {
            array_splice($trail->crumbs, 1, 0, [
                [
                    'title' => get_the_title($portfolio_page),
                    'url' => get_permalink($portfolio_page)
                ]
            ]);
        }
    }
}, 10, 2);
```

#### Icon Block Support
```php
// Add custom icons for Icon block via pattern category
add_action('init', function() {
    register_block_pattern_category('my-theme/icons', [
        'label' => __('Theme Icons', 'my-theme'),
        'description' => __('Custom icons for use in the Icon block', 'my-theme'),
    ]);
});

// For actual SVG icons in the Icon block, use block.json or PHP registration
add_action('init', function() {
    register_block_pattern('my-theme/custom-icons', [
        'title' => __('Custom Icon Set', 'my-theme'),
        'categories' => ['my-theme/icons'],
        'content' => '<!-- Pattern content with Icon blocks -->'
    ]);
});
```

### Phase 8: Testing

#### Skills to Invoke
- `playwright-skill` - Browser testing
- `webapp-testing` - Web app testing

#### Actions
1. Test across browsers
2. Verify responsive breakpoints
3. Test block editor
4. Check accessibility
5. Performance testing

#### WordPress 7.0 Testing Checklist
- [ ] Test with iframed editor
- [ ] Verify view transitions
- [ ] Check admin color scheme
- [ ] Test navigation overlays
- [ ] Verify contentOnly patterns
- [ ] Test breadcrumbs on CPT archives

#### Copy-Paste Prompts
```
Use @playwright-skill to test WordPress theme
```

## Theme Structure

```
theme-name/
├── style.css
├── functions.php
├── index.php
├── header.php
├── footer.php
├── sidebar.php
├── single.php
├── page.php
├── archive.php
├── search.php
├── 404.php
├── comments.php
├── template-parts/
│   ├── header/
│   ├── footer/
│   ├── navigation/
│   └── content/
├── patterns/           # Block patterns (WP 7.0)
├── templates/          # Site editor templates
├── inc/
│   ├── class-theme.php
│   └── supports.php
├── assets/
│   ├── css/
│   ├── js/
│   └── images/
└── languages/
```

## WordPress 7.0 Theme Checklist

- [ ] PHP 7.4+ requirement documented
- [ ] theme.json v3 schema used
- [ ] Block patterns tested
- [ ] ContentOnly editing supported
- [ ] Navigation overlays implemented
- [ ] Breadcrumb filters added for CPT
- [ ] View transitions working
- [ ] Admin refresh compatible
- [ ] CPT meta shows_in_rest
- [ ] Iframe editor tested

## Quality Gates

- [ ] All templates working
- [ ] Block editor supported
- [ ] Responsive design verified
- [ ] Accessibility checked
- [ ] Performance optimized
- [ ] Cross-browser tested
- [ ] WordPress 7.0 compatibility verified

## Related Workflow Bundles

- `wordpress` - WordPress development
- `wordpress-plugin-development` - Plugin development
- `wordpress-woocommerce` - WooCommerce

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: wordpress-woocommerce-development
description: "WooCommerce store development workflow covering store setup, payment integration, shipping configuration, customization, and WordPress 7.0 features: AI connectors, DataViews, and collaboration tools."
category: granular-workflow-bundle
risk: safe
source: personal
date_added: "2026-02-27"
---

# WordPress WooCommerce Development Workflow

## Overview

Specialized workflow for building WooCommerce stores including setup, payment gateway integration, shipping configuration, custom product types, store optimization, and WordPress 7.0 enhancements.

## WordPress 7.0 + WooCommerce Features

1. **AI Integration**
   - Auto-generate product descriptions
   - AI-powered customer service responses
   - Product summary generation
   - Marketing copy assistance

2. **DataViews for Orders**
   - Modern order management interfaces
   - Enhanced filtering and sorting
   - Activity layout for order history

3. **Real-Time Collaboration**
   - Collaborative order editing
   - Team notes and communication
   - Live inventory updates

4. **Admin Refresh**
   - Consistent WooCommerce admin styling
   - View transitions between screens

5. **Abilities API**
   - AI-powered order processing
   - Automated inventory management
   - Smart shipping recommendations

## When to Use This Workflow

Use this workflow when:
- Setting up WooCommerce stores
- Integrating payment gateways
- Configuring shipping methods
- Creating custom product types
- Building subscription products
- Implementing AI-powered features (WP 7.0)

## Workflow Phases

### Phase 1: Store Setup

#### Skills to Invoke
- `app-builder` - Project scaffolding
- `wordpress-penetration-testing` - WordPress patterns

#### Actions
1. Install WooCommerce
2. Run setup wizard
3. Configure store settings
4. Set up tax rules
5. Configure currency
6. Test with WordPress 7.0 admin

#### WordPress 7.0 + WooCommerce Setup
```php
// Minimum requirements for WP 7.0 + WooCommerce
// Add to wp-config.php for collaboration settings
define('WP_COLLABORATION_MAX_USERS', 10);

// AI features are enabled by installing a provider plugin
// Install OpenAI, Anthropic, or Gemini connector from WordPress.org
// Then configure via Settings > Connectors in admin panel
```

#### Copy-Paste Prompts
```
Use @app-builder to set up WooCommerce store
```

### Phase 2: Product Configuration

#### Skills to Invoke
- `wordpress-penetration-testing` - WooCommerce patterns

#### Actions
1. Create product categories
2. Add product attributes
3. Configure product types
4. Set up variable products
5. Add product images

#### AI-Powered Product Descriptions (WP 7.0)
```php
// Auto-generate product descriptions with AI
add_action('woocommerce_new_product', 'generate_ai_description', 10, 2);

function generate_ai_product_description($product_id, $product) {
    if ($product->get_description()) {
        return; // Skip if description exists
    }

    // Check if AI client is available
    if (!function_exists('wp_ai_client_prompt')) {
        return;
    }

    $title = $product->get_name();
    $short_description = $product->get_short_description();

    $prompt = sprintf(
        'Write a compelling WooCommerce product description for "%s" that highlights key features and benefits. Make it SEO-friendly and persuasive.',
        $title
    );

    if ($short_description) {
        $prompt .= "\n\nShort description: " . $short_description;
    }

    $result = wp_ai_client_prompt($prompt);

    if (is_wp_error($result)) {
        return;
    }

    // Use temperature for consistent output
    $result->using_temperature(0.3);
    $description = $result->generate_text();

    if ($description && !is_wp_error($description)) {
        $product->set_description($description);
        $product->save();
    }
}
```

#### Copy-Paste Prompts
```
Use @wordpress-penetration-testing to configure WooCommerce products
```

### Phase 3: Payment Integration

#### Skills to Invoke
- `payment-integration` - Payment processing
- `stripe-integration` - Stripe
- `paypal-integration` - PayPal

#### Actions
1. Choose payment gateways
2. Configure Stripe
3. Set up PayPal
4. Add offline payments
5. Test payment flows

#### WordPress 7.0 AI for Payments
```php
// AI-powered fraud detection
// Note: This is a demonstration - implement proper fraud detection with multiple signals

// Use AI to analyze order for fraud indicators
function ai_check_order_fraud($order_id) {
    // Check if AI client is available
    if (!function_exists('wp_ai_client_prompt')) {
        return false; // Default to no suspicion if AI unavailable
    }

    $order = wc_get_order($order_id);
    if (!$order) {
        return false;
    }

    $prompt = sprintf(
        'Analyze this order for potential fraud. Order total: $%s. Shipping address: %s, %s. Billing: %s. Is this suspicious? Return only "suspicious" or "clean" without explanation.',
        $order->get_total(),
        $order->get_shipping_address_1(),
        $order->get_shipping_city(),
        $order->get_billing_email()
    );

    $result = wp_ai_client_prompt($prompt);

    if (is_wp_error($result)) {
        return false;
    }

    $result->using_temperature(0.1); // Low temp for consistent classification
    $analysis = $result->generate_text();

    return (strpos($analysis, 'suspicious') !== false);
}
```

#### Copy-Paste Prompts
```
Use @stripe-integration to integrate Stripe payments
```

```
Use @paypal-integration to integrate PayPal
```

### Phase 4: Shipping Configuration

#### Skills to Invoke
- `wordpress-penetration-testing` - WooCommerce shipping

#### Actions
1. Set up shipping zones
2. Configure shipping methods
3. Add flat rate shipping
4. Set up free shipping
5. Integrate carriers

#### AI Shipping Recommendations (WP 7.0)
```php
// AI-powered shipping recommendations
add_action('woocommerce_after_checkout_form', 'ai_shipping_recommendations');

function ai_shipping_recommendations($checkout) {
    // Check if AI client is available
    if (!function_exists('wp_ai_client_prompt')) {
        return;
    }

    $cart = WC()->cart;
    if ($cart->is_empty() || !$cart->get_cart_contents_weight()) {
        return;
    }

    $prompt = sprintf(
        'Based on this cart (total weight: %d kg, destination: %s), recommend the best shipping method from: free shipping (orders over $100), flat rate ($9.99), or express ($24.99). Consider delivery time and cost efficiency. Respond with just the recommended method name.',
        $cart->get_cart_contents_weight(),
        WC()->customer->get_shipping_country()
    );

    $result = wp_ai_client_prompt($prompt);

    if (is_wp_error($result)) {
        return;
    }

    $result->using_temperature(0.1); // Low temp for consistent recommendation
    $recommendation = $result->generate_text();

    if (strpos($recommendation, 'express') !== false) {
        wc_add_notice(esc_html__('AI Recommendation: Consider Express shipping for faster delivery!', 'woocommerce'), 'info');
    }
}
```

#### Copy-Paste Prompts
```
Use @wordpress-penetration-testing to configure shipping
```

### Phase 5: Store Customization

#### Skills to Invoke
- `frontend-developer` - Store customization
- `frontend-design` - Store design

#### Actions
1. Customize product pages
2. Modify cart page
3. Style checkout flow
4. Create custom templates
5. Add custom fields

#### WordPress 7.0 Template Customization
```php
// Custom product template with WP 7.0 blocks
add_action('woocommerce_after_main_content', 'add_product_ai_chat');

function add_product_ai_chat() {
    if (!is_product()) return;

    global $product;
    ?>
    <div class="product-ai-assistant">
        <h3>AI Shopping Assistant</h3>
        <button id="ai-chat-toggle" type="button">Ask about this product</button>
        <div id="ai-chat-panel" style="display:none;">
            <div id="ai-chat-messages"></div>
            <input type="text" id="ai-chat-input" placeholder="Ask about sizing, materials, etc.">
        </div>
    </div>
    <script>
    document.getElementById('ai-chat-toggle').addEventListener('click', function() {
        const panel = document.getElementById('ai-chat-panel');
        panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
    });
    </script>
    <?php
}

// AI-powered product Q&A
add_action('wp_ajax_ai_product_question', 'handle_ai_product_question');
add_action('wp_ajax_nopriv_ai_product_question', 'handle_ai_product_question');

function handle_ai_product_question() {
    // Verify nonce for security
    if (!check_ajax_referer('ai_product_question_nonce', 'nonce', false)) {
        wp_send_json_error(['message' => 'Security check failed']);
    }

    $question = isset($_POST['question']) ? sanitize_text_field($_POST['question']) : '';
    $product_id = isset($_POST['product_id']) ? intval($_POST['product_id']) : 0;

    if (empty($question) || empty($product_id)) {
        wp_send_json_error(['message' => 'Missing required fields']);
    }

    $product = wc_get_product($product_id);
    if (!$product) {
        wp_send_json_error(['message' => 'Product not found']);
    }

    // Check if AI client is available
    if (!function_exists('wp_ai_client_prompt')) {
        wp_send_json_error(['message' => 'AI service unavailable']);
    }

    $prompt = sprintf(
        'Customer question about "%s": %s\n\nProduct details:
- Price: $%s
- SKU: %s
- Stock: %s

Answer helpfully, accurately, and concisely:',
        $product->get_name(),
        $question,
        $product->get_price(),
        $product->get_sku(),
        $product->get_stock_status()
    );

    $result = wp_ai_client_prompt($prompt);

    if (is_wp_error($result)) {
        wp_send_json_error(['message' => $result->get_error_message()]);
    }

    $result->using_temperature(0.4); // Slightly higher for more varied responses
    $answer = $result->generate_text();

    if (is_wp_error($answer)) {
        wp_send_json_error(['message' => 'Failed to generate response']);
    }

    wp_send_json_success(['answer' => $answer]);
}
```

#### Copy-Paste Prompts
```
Use @frontend-developer to customize WooCommerce templates
```

### Phase 6: Extensions

#### Skills to Invoke
- `wordpress-penetration-testing` - WooCommerce extensions

#### Actions
1. Install required extensions
2. Configure subscriptions
3. Set up bookings
4. Add memberships
5. Integrate marketplace

#### Abilities API for WooCommerce (WP 7.0)
```php
// Register ability categories first
add_action('wp_abilities_api_categories_init', function() {
    wp_register_ability_category('ecommerce', [
        'label' => __('E-Commerce', 'woocommerce'),
        'description' => __('WooCommerce store management and operations', 'woocommerce'),
    ]);
});

// Register abilities
add_action('wp_abilities_api_init', function() {
    // Register ability to update inventory
    wp_register_ability('woocommerce/update-inventory', [
        'label' => __('Update Inventory', 'woocommerce'),
        'description' => __('Update product stock quantity', 'woocommerce'),
        'category' => 'ecommerce',
        'input_schema' => [
            'type' => 'object',
            'properties' => [
                'product_id' => ['type' => 'integer', 'description' => 'Product ID to update'],
                'quantity' => ['type' => 'integer', 'description' => 'New stock quantity']
            ],
            'required' => ['product_id', 'quantity']
        ],
        'output_schema' => [
            'type' => 'object',
            'properties' => [
                'success' => ['type' => 'boolean'],
                'new_quantity' => ['type' => 'integer']
            ]
        ],
        'execute_callback' => 'woocommerce_update_inventory_handler',
        'permission_callback' => function() {
            return current_user_can('manage_woocommerce');
        }
    ]);

    // Register ability to process orders
    wp_register_ability('woocommerce/process-order', [
        'label' => __('Process Order', 'woocommerce'),
        'description' => __('Mark order as processing and trigger fulfillment', 'woocommerce'),
        'category' => 'ecommerce',
        'input_schema' => [
            'type' => 'object',
            'properties' => [
                'order_id' => ['type' => 'integer', 'description' => 'Order ID to process']
            ],
            'required' => ['order_id']
        ],
        'output_schema' => [
            'type' => 'object',
            'properties' => [
                'success' => ['type' => 'boolean'],
                'status' => ['type' => 'string']
            ]
        ],
        'execute_callback' => 'woocommerce_process_order_handler',
        'permission_callback' => function() {
            return current_user_can('manage_woocommerce');
        }
    ]);
});

// Handler for inventory update
function woocommerce_update_inventory_handler($input) {
    $product_id = isset($input['product_id']) ? absint($input['product_id']) : 0;
    $quantity = isset($input['quantity']) ? absint($input['quantity']) : 0;

    $product = wc_get_product($product_id);
    if (!$product) {
        return new WP_Error('invalid_product', 'Product not found');
    }

    // Update stock
    wc_update_product_stock($product, $quantity);

    return [
        'success' => true,
        'new_quantity' => $product->get_stock_quantity()
    ];
}

// Handler for order processing
function woocommerce_process_order_handler($input) {
    $order_id = isset($input['order_id']) ? absint($input['order_id']) : 0;

    $order = wc_get_order($order_id);
    if (!$order) {
        return new WP_Error('invalid_order', 'Order not found');
    }

    $order->update_status('processing');

    return [
        'success' => true,
        'status' => 'processing'
    ];
}
```

#### Copy-Paste Prompts
```
Use @wordpress-penetration-testing to configure WooCommerce extensions
```

### Phase 7: Optimization

#### Skills to Invoke
- `web-performance-optimization` - Performance
- `database-optimizer` - Database optimization

#### Actions
1. Optimize product images
2. Enable caching
3. Optimize database
4. Configure CDN
5. Set up lazy loading

#### WordPress 7.0 Performance
- Client-side media processing
- Font Library enabled
- Responsive grid block
- View transitions for perceived performance

#### Copy-Paste Prompts
```
Use @web-performance-optimization to optimize WooCommerce store
```

### Phase 8: Testing

#### Skills to Invoke
- `playwright-skill` - E2E testing
- `test-automator` - Test automation

#### Actions
1. Test checkout flow
2. Verify payment processing
3. Test email notifications
4. Check mobile experience
5. Performance testing

#### WordPress 7.0 Testing
- Test with new admin interface
- Verify AI features work
- Test DataViews for orders
- Verify collaboration features

#### AI-Powered Store Testing
```php
// Automated AI testing for fraud detection during checkout
add_action('woocommerce_after_checkout_validation', 'ai_validate_order', 20);

function ai_validate_order($fields, $errors) {
    // Skip if AI is not available
    if (!function_exists('wp_ai_client_prompt')) {
        return;
    }

    // Skip for logged-in users (assumed trusted)
    if (is_user_logged_in()) {
        return;
    }

    $order_data = [
        'email' => isset($fields['billing_email']) ? $fields['billing_email'] : '',
        'phone' => isset($fields['billing_phone']) ? $fields['billing_phone'] : '',
        'address' => isset($fields['billing_address_1']) ? $fields['billing_address_1'] : '',
    ];

    // Skip if insufficient data
    if (empty($order_data['email'])) {
        return;
    }

    $prompt = sprintf(
        'This is a checkout validation. Check if these details seem legitimate: email=%s, phone=%s, address=%s. Return only "valid" or "suspicious" without additional text.',
        sanitize_email($order_data['email']),
        sanitize_text_field($order_data['phone']),
        sanitize_text_field($order_data['address'])
    );

    $result = wp_ai_client_prompt($prompt);

    if (is_wp_error($result)) {
        // Don't block checkout on AI errors
        return;
    }

    $result->using_temperature(0.1); // Low temp for consistent classification
    $response = $result->generate_text();

    if (is_wp_error($response)) {
        return;
    }

    if (strpos($response, 'suspicious') !== false) {
        $errors->add('validation', __('Additional verification may be needed for this order. We will contact you if needed.', 'woocommerce'));
    }
}
```

#### Copy-Paste Prompts
```
Use @playwright-skill to test WooCommerce checkout flow
```

## WooCommerce + WordPress 7.0 AI Use Cases

1. **Product Descriptions**
   - Auto-generate from product attributes
   - Translate descriptions
   - SEO optimization

2. **Customer Service**
   - AI chatbot for common questions
   - Order status lookup
   - Return processing

3. **Inventory Management**
   - Demand forecasting
   - Low stock alerts
   - Reorder recommendations

4. **Marketing**
   - Personalized emails
   - Product recommendations
   - Abandoned cart recovery

5. **Order Processing**
   - Fraud detection
   - Shipping optimization
   - Invoice generation

## Quality Gates

- [ ] Products displaying correctly
- [ ] Checkout flow working
- [ ] Payments processing
- [ ] Shipping calculating
- [ ] Emails sending
- [ ] Mobile responsive
- [ ] AI features tested (WP 7.0)
- [ ] DataViews working (WP 7.0)

## Related Workflow Bundles

- `wordpress` - WordPress development
- `wordpress-theme-development` - Theme development
- `wordpress-plugin-development` - Plugin development
- `payment-integration` - Payment processing

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: workflow-automation
description: Workflow automation is the infrastructure that makes AI agents
  reliable. Without durable execution, a network hiccup during a 10-step payment
  flow means lost money and angry customers. With it, workflows resume exactly
  where they left off.
risk: critical
source: vibeship-spawner-skills (Apache 2.0)
date_added: 2026-02-27
---

# Workflow Automation

Workflow automation is the infrastructure that makes AI agents reliable.
Without durable execution, a network hiccup during a 10-step payment
flow means lost money and angry customers. With it, workflows resume
exactly where they left off.

This skill covers the platforms (n8n, Temporal, Inngest) and patterns
(sequential, parallel, orchestrator-worker) that turn brittle scripts
into production-grade automation.

Key insight: The platforms make different tradeoffs. n8n optimizes for
accessibility, Temporal for correctness, Inngest for developer experience.
Pick based on your actual needs, not hype.

## Principles

- Durable execution is non-negotiable for money or state-critical workflows
- Events are the universal language of workflow triggers
- Steps are checkpoints - each should be independently retryable
- Start simple, add complexity only when reliability demands it
- Observability isn't optional - you need to see where workflows fail
- Workflows and agents co-evolve - design for both

## Capabilities

- workflow-automation
- workflow-orchestration
- durable-execution
- event-driven-workflows
- step-functions
- job-queues
- background-jobs
- scheduled-tasks

## Scope

- multi-agent-coordination → multi-agent-orchestration
- ci-cd-pipelines → devops
- data-pipelines → data-engineer
- api-design → api-designer

## Tooling

### Platforms

- n8n - When: Low-code automation, quick prototyping, non-technical users Note: Self-hostable, 400+ integrations, great for visual workflows
- Temporal - When: Mission-critical workflows, financial transactions, microservices Note: Strongest durability guarantees, steeper learning curve
- Inngest - When: Event-driven serverless, TypeScript codebases, AI workflows Note: Best developer experience, works with any hosting
- AWS Step Functions - When: AWS-native stacks, existing Lambda functions Note: Tight AWS integration, JSON-based workflow definition
- Azure Durable Functions - When: Azure stacks, .NET or TypeScript Note: Good AI agent support, checkpoint and replay

## Patterns

### Sequential Workflow Pattern

Steps execute in order, each output becomes next input

**When to use**: Content pipelines, data processing, ordered operations

# SEQUENTIAL WORKFLOW:

"""
Step 1 → Step 2 → Step 3 → Output
  ↓         ↓         ↓
(checkpoint at each step)
"""

## Inngest Example (TypeScript)
"""
import { inngest } from "./client";

export const processOrder = inngest.createFunction(
  { id: "process-order" },
  { event: "order/created" },
  async ({ event, step }) => {
    // Step 1: Validate order
    const validated = await step.run("validate-order", async () => {
      return validateOrder(event.data.order);
    });

    // Step 2: Process payment (durable - survives crashes)
    const payment = await step.run("process-payment", async () => {
      return chargeCard(validated.paymentMethod, validated.total);
    });

    // Step 3: Create shipment
    const shipment = await step.run("create-shipment", async () => {
      return createShipment(validated.items, validated.address);
    });

    // Step 4: Send confirmation
    await step.run("send-confirmation", async () => {
      return sendEmail(validated.email, { payment, shipment });
    });

    return { success: true, orderId: event.data.orderId };
  }
);
"""

## Temporal Example (TypeScript)
"""
import { proxyActivities } from '@temporalio/workflow';
import type * as activities from './activities';

const { validateOrder, chargeCard, createShipment, sendEmail } =
  proxyActivities<typeof activities>({
    startToCloseTimeout: '30 seconds',
    retry: {
      maximumAttempts: 3,
      backoffCoefficient: 2,
    }
  });

export async function processOrderWorkflow(order: Order): Promise<void> {
  const validated = await validateOrder(order);
  const payment = await chargeCard(validated.paymentMethod, validated.total);
  const shipment = await createShipment(validated.items, validated.address);
  await sendEmail(validated.email, { payment, shipment });
}
"""

## n8n Pattern
"""
[Webhook: order.created]
    ↓
[HTTP Request: Validate Order]
    ↓
[HTTP Request: Process Payment]
    ↓
[HTTP Request: Create Shipment]
    ↓
[Send Email: Confirmation]

Configure each node with retry on failure.
Use Error Trigger for dead letter handling.
"""

### Parallel Workflow Pattern

Independent steps run simultaneously, aggregate results

**When to use**: Multiple independent analyses, data from multiple sources

# PARALLEL WORKFLOW:

"""
        ┌→ Step A ─┐
Input ──┼→ Step B ─┼→ Aggregate → Output
        └→ Step C ─┘
"""

## Inngest Example
"""
export const analyzeDocument = inngest.createFunction(
  { id: "analyze-document" },
  { event: "document/uploaded" },
  async ({ event, step }) => {
    // Run analyses in parallel
    const [security, performance, compliance] = await Promise.all([
      step.run("security-analysis", () =>
        analyzeForSecurityIssues(event.data.document)
      ),
      step.run("performance-analysis", () =>
        analyzeForPerformance(event.data.document)
      ),
      step.run("compliance-analysis", () =>
        analyzeForCompliance(event.data.document)
      ),
    ]);

    // Aggregate results
    const report = await step.run("generate-report", () =>
      generateReport({ security, performance, compliance })
    );

    return report;
  }
);
"""

## AWS Step Functions (Amazon States Language)
"""
{
  "Type": "Parallel",
  "Branches": [
    {
      "StartAt": "SecurityAnalysis",
      "States": {
        "SecurityAnalysis": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:...:security-analyzer",
          "End": true
        }
      }
    },
    {
      "StartAt": "PerformanceAnalysis",
      "States": {
        "PerformanceAnalysis": {
          "Type": "Task",
          "Resource": "arn:aws:lambda:...:performance-analyzer",
          "End": true
        }
      }
    }
  ],
  "Next": "AggregateResults"
}
"""

### Orchestrator-Worker Pattern

Central coordinator dispatches work to specialized workers

**When to use**: Complex tasks requiring different expertise, dynamic subtask creation

# ORCHESTRATOR-WORKER PATTERN:

"""
┌─────────────────────────────────────┐
│          ORCHESTRATOR               │
│  - Analyzes task                    │
│  - Creates subtasks                 │
│  - Dispatches to workers            │
│  - Aggregates results               │
└─────────────────────────────────────┘
                │
    ┌───────────┼───────────┐
    ▼           ▼           ▼
┌───────┐  ┌───────┐  ┌───────┐
│Worker1│  │Worker2│  │Worker3│
│Create │  │Modify │  │Delete │
└───────┘  └───────┘  └───────┘
"""

## Temporal Example
"""
export async function orchestratorWorkflow(task: ComplexTask) {
  // Orchestrator decides what work needs to be done
  const plan = await analyzeTask(task);

  // Dispatch to specialized worker workflows
  const results = await Promise.all(
    plan.subtasks.map(subtask => {
      switch (subtask.type) {
        case 'create':
          return executeChild(createWorkerWorkflow, { args: [subtask] });
        case 'modify':
          return executeChild(modifyWorkerWorkflow, { args: [subtask] });
        case 'delete':
          return executeChild(deleteWorkerWorkflow, { args: [subtask] });
      }
    })
  );

  // Aggregate results
  return aggregateResults(results);
}
"""

## Inngest with AI Orchestration
"""
export const aiOrchestrator = inngest.createFunction(
  { id: "ai-orchestrator" },
  { event: "task/complex" },
  async ({ event, step }) => {
    // AI decides what needs to be done
    const plan = await step.run("create-plan", async () => {
      return await llm.chat({
        messages: [
          { role: "system", content: "Break this task into subtasks..." },
          { role: "user", content: event.data.task }
        ]
      });
    });

    // Execute each subtask as a durable step
    const results = [];
    for (const subtask of plan.subtasks) {
      const result = await step.run(`execute-${subtask.id}`, async () => {
        return executeSubtask(subtask);
      });
      results.push(result);
    }

    // Final synthesis
    return await step.run("synthesize", async () => {
      return synthesizeResults(results);
    });
  }
);
"""

### Event-Driven Trigger Pattern

Workflows triggered by events, not schedules

**When to use**: Reactive systems, user actions, webhook integrations

# EVENT-DRIVEN TRIGGERS:

## Inngest Event-Based
"""
// Define events with TypeScript types
type Events = {
  "user/signed.up": {
    data: { userId: string; email: string };
  };
  "order/completed": {
    data: { orderId: string; total: number };
  };
};

// Function triggered by event
export const onboardUser = inngest.createFunction(
  { id: "onboard-user" },
  { event: "user/signed.up" },  // Trigger on this event
  async ({ event, step }) => {
    // Wait 1 hour, then send welcome email
    await step.sleep("wait-for-exploration", "1 hour");

    await step.run("send-welcome", async () => {
      return sendWelcomeEmail(event.data.email);
    });

    // Wait 3 days for engagement check
    await step.sleep("wait-for-engagement", "3 days");

    const engaged = await step.run("check-engagement", async () => {
      return checkUserEngagement(event.data.userId);
    });

    if (!engaged) {
      await step.run("send-nudge", async () => {
        return sendNudgeEmail(event.data.email);
      });
    }
  }
);

// Send events from anywhere
await inngest.send({
  name: "user/signed.up",
  data: { userId: "123", email: "user@example.com" }
});
"""

## n8n Webhook Trigger
"""
[Webhook: POST /api/webhooks/order]
    ↓
[Switch: event.type]
    ↓ order.created
[Process New Order Subworkflow]
    ↓ order.cancelled
[Handle Cancellation Subworkflow]
"""

### Retry and Recovery Pattern

Automatic retry with backoff, dead letter handling

**When to use**: Any workflow with external dependencies

# RETRY AND RECOVERY:

## Temporal Retry Configuration
"""
const activities = proxyActivities<typeof activitiesType>({
  startToCloseTimeout: '30 seconds',
  retry: {
    initialInterval: '1 second',
    backoffCoefficient: 2,
    maximumInterval: '1 minute',
    maximumAttempts: 5,
    nonRetryableErrorTypes: [
      'ValidationError',      // Don't retry validation failures
      'InsufficientFunds',    // Don't retry payment failures
    ]
  }
});
"""

## Inngest Retry Configuration
"""
export const processPayment = inngest.createFunction(
  {
    id: "process-payment",
    retries: 5,  // Retry up to 5 times
  },
  { event: "payment/initiated" },
  async ({ event, step, attempt }) => {
    // attempt is 0-indexed retry count

    const result = await step.run("charge-card", async () => {
      try {
        return await stripe.charges.create({...});
      } catch (error) {
        if (error.code === 'card_declined') {
          // Don't retry card declines
          throw new NonRetriableError("Card declined");
        }
        throw error;  // Retry other errors
      }
    });

    return result;
  }
);
"""

## Dead Letter Handling
"""
// n8n: Use Error Trigger node
[Error Trigger]
    ↓
[Log to Error Database]
    ↓
[Send Alert to Slack]
    ↓
[Create Ticket in Jira]

// Inngest: Handle in onFailure
export const myFunction = inngest.createFunction(
  {
    id: "my-function",
    onFailure: async ({ error, event, step }) => {
      await step.run("alert-team", async () => {
        await slack.postMessage({
          channel: "#errors",
          text: `Function failed: ${error.message}`
        });
      });
    }
  },
  { event: "..." },
  async ({ step }) => { ... }
);
"""

### Scheduled Workflow Pattern

Time-based triggers for recurring tasks

**When to use**: Daily reports, periodic sync, batch processing

# SCHEDULED WORKFLOWS:

## Inngest Cron
"""
export const dailyReport = inngest.createFunction(
  { id: "daily-report" },
  { cron: "0 9 * * *" },  // Every day at 9 AM
  async ({ step }) => {
    const data = await step.run("gather-metrics", async () => {
      return gatherDailyMetrics();
    });

    await step.run("generate-report", async () => {
      return generateAndSendReport(data);
    });
  }
);

export const syncInventory = inngest.createFunction(
  { id: "sync-inventory" },
  { cron: "*/15 * * * *" },  // Every 15 minutes
  async ({ step }) => {
    await step.run("sync", async () => {
      return syncWithSupplier();
    });
  }
);
"""

## Temporal Cron Workflow
"""
// Schedule workflow to run on cron
const handle = await client.workflow.start(dailyReportWorkflow, {
  taskQueue: 'reports',
  workflowId: 'daily-report',
  cronSchedule: '0 9 * * *',  // 9 AM daily
});
"""

## n8n Schedule Trigger
"""
[Schedule Trigger: Every day at 9:00 AM]
    ↓
[HTTP Request: Get Metrics]
    ↓
[Code Node: Generate Report]
    ↓
[Send Email: Report]
"""

## Sharp Edges

### Non-Idempotent Steps in Durable Workflows

Severity: CRITICAL

Situation: Writing workflow steps that modify external state

Symptoms:
Customer charged twice. Email sent three times. Database record
created multiple times. Workflow retries cause duplicate side effects.

Why this breaks:
Durable execution replays workflows from the beginning on restart.
If step 3 crashes and the workflow resumes, steps 1 and 2 run again.
Without idempotency keys, external services don't know these are retries.

Recommended fix:

# ALWAYS use idempotency keys for external calls:

### Stripe example:
await stripe.paymentIntents.create({
  amount: 1000,
  currency: 'usd',
  idempotency_key: `order-${orderId}-payment`  # Critical!
});

### Email example:
await step.run("send-confirmation", async () => {
  const alreadySent = await checkEmailSent(orderId);
  if (alreadySent) return { skipped: true };
  return sendEmail(customer, orderId);
});

### Database example:
await db.query(`
  INSERT INTO orders (id, ...) VALUES ($1, ...)
  ON CONFLICT (id) DO NOTHING
`, [orderId]);

# Generate idempotency key from stable inputs, not random values

### Workflow Runs for Hours/Days Without Checkpoints

Severity: HIGH

Situation: Long-running workflows with infrequent steps

Symptoms:
Memory consumption grows. Worker timeouts. Lost progress after
crashes. "Workflow exceeded maximum duration" errors.

Why this breaks:
Workflows hold state in memory until checkpointed. A workflow that
runs for 24 hours with one step per hour accumulates state for 24h.
Workers have memory limits. Functions have execution time limits.

Recommended fix:

# Break long workflows into checkpointed steps:

### WRONG - one long step:
await step.run("process-all", async () => {
  for (const item of thousandItems) {
    await processItem(item);  // Hours of work, one checkpoint
  }
});

### CORRECT - many small steps:
for (const item of thousandItems) {
  await step.run(`process-${item.id}`, async () => {
    return processItem(item);  // Checkpoint after each
  });
}

## For very long waits, use sleep:
await step.sleep("wait-for-trial", "14 days");
// Doesn't consume resources while waiting

## Consider child workflows for long processes:
await step.invoke("process-batch", {
  function: batchProcessor,
  data: { items: batch }
});

### Activities Without Timeout Configuration

Severity: HIGH

Situation: Calling external services from workflow activities

Symptoms:
Workflows hang indefinitely. Worker pool exhausted. Dead workflows
that never complete or fail. Manual intervention needed to kill stuck
workflows.

Why this breaks:
External APIs can hang forever. Without timeout, your workflow waits
forever. Unlike HTTP clients, workflow activities don't have default
timeouts in most platforms.

Recommended fix:

# ALWAYS set timeouts on activities:

### Temporal:
const activities = proxyActivities<typeof activitiesType>({
  startToCloseTimeout: '30 seconds',  # Required!
  scheduleToCloseTimeout: '5 minutes',
  heartbeatTimeout: '10 seconds',  # For long activities
  retry: {
    maximumAttempts: 3,
    initialInterval: '1 second',
  }
});

### Inngest:
await step.run("call-api", { timeout: "30s" }, async () => {
  return fetch(url, { signal: AbortSignal.timeout(25000) });
});

## AWS Step Functions:
{
  "Type": "Task",
  "TimeoutSeconds": 30,
  "HeartbeatSeconds": 10,
  "Resource": "arn:aws:lambda:..."
}

# Rule: Activity timeout < Workflow timeout

### Side Effects Outside Step/Activity Boundaries

Severity: CRITICAL

Situation: Writing code that runs during workflow replay

Symptoms:
Random failures on replay. "Workflow corrupted" errors. Different
behavior on replay than initial run. Non-determinism errors.

Why this breaks:
Workflow code runs on EVERY replay. If you generate a random ID in
workflow code, you get a different ID each replay. If you read the
current time, you get a different time. This breaks determinism.

Recommended fix:

# WRONG - side effects in workflow code:
export async function orderWorkflow(order) {
  const orderId = uuid();  // Different every replay!
  const now = new Date();  // Different every replay!
  await activities.process(orderId, now);
}

# CORRECT - side effects in activities:
export async function orderWorkflow(order) {
  const orderId = await activities.generateOrderId();  # Recorded
  const now = await activities.getCurrentTime();       # Recorded
  await activities.process(orderId, now);
}

# Also CORRECT - Temporal workflow.now() and sideEffect:
import { sideEffect } from '@temporalio/workflow';

const orderId = await sideEffect(() => uuid());
const now = workflow.now();  # Deterministic replay-safe time

# Side effects that are safe in workflow code:
# - Reading function arguments
# - Simple calculations (no randomness)
# - Logging (usually)

### Retry Configuration Without Exponential Backoff

Severity: MEDIUM

Situation: Configuring retry behavior for failing steps

Symptoms:
Overwhelming failing services. Rate limiting. Cascading failures.
Retry storms causing outages. Being blocked by external APIs.

Why this breaks:
When a service is struggling, immediate retries make it worse.
100 workflows retrying instantly = 100 requests hitting a service
that's already failing. Backoff gives the service time to recover.

Recommended fix:

# ALWAYS use exponential backoff:

### Temporal:
const activities = proxyActivities({
  retry: {
    initialInterval: '1 second',
    backoffCoefficient: 2,       # 1s, 2s, 4s, 8s, 16s...
    maximumInterval: '1 minute',  # Cap the backoff
    maximumAttempts: 5,
  }
});

### Inngest (built-in backoff):
{
  id: "my-function",
  retries: 5,  # Uses exponential backoff by default
}

### Manual backoff:
const backoff = (attempt) => {
  const base = 1000;
  const max = 60000;
  const delay = Math.min(base * Math.pow(2, attempt), max);
  const jitter = delay * 0.1 * Math.random();
  return delay + jitter;
};

# Add jitter to prevent thundering herd

### Storing Large Data in Workflow State

Severity: HIGH

Situation: Passing large payloads between workflow steps

Symptoms:
Slow workflow execution. Memory errors. "Payload too large" errors.
Expensive storage costs. Slow replays.

Why this breaks:
Workflow state is persisted and replayed. A 10MB payload is stored,
serialized, and deserialized on every step. This adds latency and
cost. Some platforms have hard limits (e.g., Step Functions 256KB).

Recommended fix:

# WRONG - large data in workflow:
await step.run("fetch-data", async () => {
  const largeDataset = await fetchAllRecords();  // 100MB!
  return largeDataset;  // Stored in workflow state
});

# CORRECT - store reference, not data:
await step.run("fetch-data", async () => {
  const largeDataset = await fetchAllRecords();
  const s3Key = await uploadToS3(largeDataset);
  return { s3Key };  // Just the reference
});

const processed = await step.run("process-data", async () => {
  const data = await downloadFromS3(fetchResult.s3Key);
  return processData(data);
});

# For Step Functions, use S3 for large payloads:
{
  "Type": "Task",
  "Resource": "arn:aws:states:::s3:putObject",
  "Parameters": {
    "Bucket": "my-bucket",
    "Key.$": "$.outputKey",
    "Body.$": "$.largeData"
  }
}

### Missing Dead Letter Queue or Failure Handler

Severity: HIGH

Situation: Workflows that exhaust all retries

Symptoms:
Failed workflows silently disappear. No alerts when things break.
Customer issues discovered days later. Manual recovery impossible.

Why this breaks:
Even with retries, some workflows will fail permanently. Without
dead letter handling, you don't know they failed. The customer
waits forever, you're unaware, and there's no data to debug.

Recommended fix:

# Inngest onFailure handler:
export const myFunction = inngest.createFunction(
  {
    id: "process-order",
    onFailure: async ({ error, event, step }) => {
      // Log to error tracking
      await step.run("log-error", () =>
        sentry.captureException(error, { extra: { event } })
      );

      // Alert team
      await step.run("alert", () =>
        slack.postMessage({
          channel: "#alerts",
          text: `Order ${event.data.orderId} failed: ${error.message}`
        })
      );

      // Queue for manual review
      await step.run("queue-review", () =>
        db.insert(failedOrders, { orderId, error, event })
      );
    }
  },
  { event: "order/created" },
  async ({ event, step }) => { ... }
);

# n8n Error Trigger:
[Error Trigger]  →  [Log to DB]  →  [Slack Alert]  →  [Create Ticket]

# Temporal: Use workflow.failed or workflow signals

### n8n Workflow Without Error Trigger

Severity: MEDIUM

Situation: Building production n8n workflows

Symptoms:
Workflow fails silently. Errors only visible in execution logs.
No alerts, no recovery, no visibility until someone notices.

Why this breaks:
n8n doesn't notify on failure by default. Without an Error Trigger
node connected to alerting, failures are only visible in the UI.
Production failures go unnoticed.

Recommended fix:

# Every production n8n workflow needs:

1. Error Trigger node
   - Catches any node failure in the workflow
   - Provides error details and context

2. Connected error handling:
   [Error Trigger]
       ↓
   [Set: Extract Error Details]
       ↓
   [HTTP: Log to Error Service]
       ↓
   [Slack/Email: Alert Team]

3. Consider dead letter pattern:
   [Error Trigger]
       ↓
   [Redis/Postgres: Store Failed Job]
       ↓
   [Separate Recovery Workflow]

# Also use:
- Retry on node failures (built-in)
- Node timeout settings
- Workflow timeout

### Long-Running Temporal Activities Without Heartbeat

Severity: MEDIUM

Situation: Activities that run for more than a few seconds

Symptoms:
Activity timeouts even when work is progressing. Lost work when
workers restart. Can't cancel long-running activities.

Why this breaks:
Temporal detects stuck activities via heartbeat. Without heartbeat,
Temporal can't tell if activity is working or stuck. Long activities
appear hung, may timeout, and can't be gracefully cancelled.

Recommended fix:

# For any activity > 10 seconds, add heartbeat:

import { heartbeat, activityInfo } from '@temporalio/activity';

export async function processLargeFile(fileUrl: string): Promise<void> {
  const chunks = await downloadChunks(fileUrl);

  for (let i = 0; i < chunks.length; i++) {
    // Check for cancellation
    const { cancelled } = activityInfo();
    if (cancelled) {
      throw new CancelledFailure('Activity cancelled');
    }

    await processChunk(chunks[i]);

    // Report progress
    heartbeat({ progress: (i + 1) / chunks.length });
  }
}

# Configure heartbeat timeout:
const activities = proxyActivities({
  startToCloseTimeout: '10 minutes',
  heartbeatTimeout: '30 seconds',  # Must heartbeat every 30s
});

# If no heartbeat for 30s, activity is considered stuck

## Validation Checks

### External Calls Without Idempotency Key

Severity: ERROR

Stripe/payment calls should use idempotency keys

Message: Payment call without idempotency_key. Add idempotency key to prevent duplicate charges on retry.

### Email Sending Without Deduplication

Severity: WARNING

Email sends in workflows should check for already-sent

Message: Email sent in workflow without deduplication check. Retries may send duplicate emails.

### Temporal Activities Without Timeout

Severity: ERROR

All Temporal activities need timeout configuration

Message: proxyActivities without timeout. Add startToCloseTimeout to prevent indefinite hangs.

### Inngest Steps Calling External APIs Without Timeout

Severity: WARNING

External API calls should have timeouts

Message: External API call in step without timeout. Add timeout to prevent workflow hangs.

### Random Values in Workflow Code

Severity: ERROR

Random values break determinism on replay

Message: Random value in workflow code. Move to activity/step or use sideEffect.

### Date.now() in Workflow Code

Severity: ERROR

Current time breaks determinism on replay

Message: Current time in workflow code. Use workflow.now() or move to activity/step.

### Inngest Function Without onFailure Handler

Severity: WARNING

Production functions should have failure handlers

Message: Inngest function without onFailure handler. Add failure handling for production reliability.

### Step Without Error Handling

Severity: WARNING

Steps should handle errors gracefully

Message: Step without try/catch. Consider handling specific error cases.

### Potentially Large Data Returned from Step

Severity: INFO

Large data in workflow state slows execution

Message: Returning potentially large data from step. Consider storing in S3/DB and returning reference.

### Retry Without Backoff Configuration

Severity: WARNING

Retries should use exponential backoff

Message: Retry configured without backoff. Add backoffCoefficient and initialInterval.

## Collaboration

### Delegation Triggers

- user needs multi-agent coordination -> multi-agent-orchestration (Workflow provides infrastructure, orchestration provides patterns)
- user needs tool building for workflows -> agent-tool-builder (Tools that workflows can invoke)
- user needs Zapier/Make integration -> zapier-make-patterns (No-code automation platforms)
- user needs browser automation in workflow -> browser-automation (Playwright/Puppeteer activities)
- user needs computer control in workflow -> computer-use-agents (Desktop automation activities)
- user needs LLM integration in workflow -> llm-architect (AI-powered workflow steps)

## Related Skills

Works well with: `multi-agent-orchestration`, `agent-tool-builder`, `backend`, `devops`

## When to Use
- User mentions or implies: workflow
- User mentions or implies: automation
- User mentions or implies: n8n
- User mentions or implies: temporal
- User mentions or implies: inngest
- User mentions or implies: step function
- User mentions or implies: background job
- User mentions or implies: durable execution
- User mentions or implies: event-driven
- User mentions or implies: scheduled task
- User mentions or implies: job queue
- User mentions or implies: cron
- User mentions or implies: trigger

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: workflow-orchestration-patterns
description: "Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems."
risk: none
source: community
date_added: "2026-02-27"
---

# Workflow Orchestration Patterns

Master workflow orchestration architecture with Temporal, covering fundamental design decisions, resilience patterns, and best practices for building reliable distributed systems.

## Use this skill when

- Working on workflow orchestration patterns tasks or workflows
- Needing guidance, best practices, or checklists for workflow orchestration patterns

## Do not use this skill when

- The task is unrelated to workflow orchestration patterns
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## When to Use Workflow Orchestration

### Ideal Use Cases (Source: docs.temporal.io)

- **Multi-step processes** spanning machines/services/databases
- **Distributed transactions** requiring all-or-nothing semantics
- **Long-running workflows** (hours to years) with automatic state persistence
- **Failure recovery** that must resume from last successful step
- **Business processes**: bookings, orders, campaigns, approvals
- **Entity lifecycle management**: inventory tracking, account management, cart workflows
- **Infrastructure automation**: CI/CD pipelines, provisioning, deployments
- **Human-in-the-loop** systems requiring timeouts and escalations

### When NOT to Use

- Simple CRUD operations (use direct API calls)
- Pure data processing pipelines (use Airflow, batch processing)
- Stateless request/response (use standard APIs)
- Real-time streaming (use Kafka, event processors)

## Critical Design Decision: Workflows vs Activities

**The Fundamental Rule** (Source: temporal.io/blog/workflow-engine-principles):

- **Workflows** = Orchestration logic and decision-making
- **Activities** = External interactions (APIs, databases, network calls)

### Workflows (Orchestration)

**Characteristics:**

- Contain business logic and coordination
- **MUST be deterministic** (same inputs → same outputs)
- **Cannot** perform direct external calls
- State automatically preserved across failures
- Can run for years despite infrastructure failures

**Example workflow tasks:**

- Decide which steps to execute
- Handle compensation logic
- Manage timeouts and retries
- Coordinate child workflows

### Activities (External Interactions)

**Characteristics:**

- Handle all external system interactions
- Can be non-deterministic (API calls, DB writes)
- Include built-in timeouts and retry logic
- **Must be idempotent** (calling N times = calling once)
- Short-lived (seconds to minutes typically)

**Example activity tasks:**

- Call payment gateway API
- Write to database
- Send emails or notifications
- Query external services

### Design Decision Framework

```
Does it touch external systems? → Activity
Is it orchestration/decision logic? → Workflow
```

## Core Workflow Patterns

### 1. Saga Pattern with Compensation

**Purpose**: Implement distributed transactions with rollback capability

**Pattern** (Source: temporal.io/blog/compensating-actions-part-of-a-complete-breakfast-with-sagas):

```
For each step:
  1. Register compensation BEFORE executing
  2. Execute the step (via activity)
  3. On failure, run all compensations in reverse order (LIFO)
```

**Example: Payment Workflow**

1. Reserve inventory (compensation: release inventory)
2. Charge payment (compensation: refund payment)
3. Fulfill order (compensation: cancel fulfillment)

**Critical Requirements:**

- Compensations must be idempotent
- Register compensation BEFORE executing step
- Run compensations in reverse order
- Handle partial failures gracefully

### 2. Entity Workflows (Actor Model)

**Purpose**: Long-lived workflow representing single entity instance

**Pattern** (Source: docs.temporal.io/evaluate/use-cases-design-patterns):

- One workflow execution = one entity (cart, account, inventory item)
- Workflow persists for entity lifetime
- Receives signals for state changes
- Supports queries for current state

**Example Use Cases:**

- Shopping cart (add items, checkout, expiration)
- Bank account (deposits, withdrawals, balance checks)
- Product inventory (stock updates, reservations)

**Benefits:**

- Encapsulates entity behavior
- Guarantees consistency per entity
- Natural event sourcing

### 3. Fan-Out/Fan-In (Parallel Execution)

**Purpose**: Execute multiple tasks in parallel, aggregate results

**Pattern:**

- Spawn child workflows or parallel activities
- Wait for all to complete
- Aggregate results
- Handle partial failures

**Scaling Rule** (Source: temporal.io/blog/workflow-engine-principles):

- Don't scale individual workflows
- For 1M tasks: spawn 1K child workflows × 1K tasks each
- Keep each workflow bounded

### 4. Async Callback Pattern

**Purpose**: Wait for external event or human approval

**Pattern:**

- Workflow sends request and waits for signal
- External system processes asynchronously
- Sends signal to resume workflow
- Workflow continues with response

**Use Cases:**

- Human approval workflows
- Webhook callbacks
- Long-running external processes

## State Management and Determinism

### Automatic State Preservation

**How Temporal Works** (Source: docs.temporal.io/workflows):

- Complete program state preserved automatically
- Event History records every command and event
- Seamless recovery from crashes
- Applications restore pre-failure state

### Determinism Constraints

**Workflows Execute as State Machines**:

- Replay behavior must be consistent
- Same inputs → identical outputs every time

**Prohibited in Workflows** (Source: docs.temporal.io/workflows):

- ❌ Threading, locks, synchronization primitives
- ❌ Random number generation (`random()`)
- ❌ Global state or static variables
- ❌ System time (`datetime.now()`)
- ❌ Direct file I/O or network calls
- ❌ Non-deterministic libraries

**Allowed in Workflows**:

- ✅ `workflow.now()` (deterministic time)
- ✅ `workflow.random()` (deterministic random)
- ✅ Pure functions and calculations
- ✅ Calling activities (non-deterministic operations)

### Versioning Strategies

**Challenge**: Changing workflow code while old executions still running

**Solutions**:

1. **Versioning API**: Use `workflow.get_version()` for safe changes
2. **New Workflow Type**: Create new workflow, route new executions to it
3. **Backward Compatibility**: Ensure old events replay correctly

## Resilience and Error Handling

### Retry Policies

**Default Behavior**: Temporal retries activities forever

**Configure Retry**:

- Initial retry interval
- Backoff coefficient (exponential backoff)
- Maximum interval (cap retry delay)
- Maximum attempts (eventually fail)

**Non-Retryable Errors**:

- Invalid input (validation failures)
- Business rule violations
- Permanent failures (resource not found)

### Idempotency Requirements

**Why Critical** (Source: docs.temporal.io/activities):

- Activities may execute multiple times
- Network failures trigger retries
- Duplicate execution must be safe

**Implementation Strategies**:

- Idempotency keys (deduplication)
- Check-then-act with unique constraints
- Upsert operations instead of insert
- Track processed request IDs

### Activity Heartbeats

**Purpose**: Detect stalled long-running activities

**Pattern**:

- Activity sends periodic heartbeat
- Includes progress information
- Timeout if no heartbeat received
- Enables progress-based retry

## Best Practices

### Workflow Design

1. **Keep workflows focused** - Single responsibility per workflow
2. **Small workflows** - Use child workflows for scalability
3. **Clear boundaries** - Workflow orchestrates, activities execute
4. **Test locally** - Use time-skipping test environment

### Activity Design

1. **Idempotent operations** - Safe to retry
2. **Short-lived** - Seconds to minutes, not hours
3. **Timeout configuration** - Always set timeouts
4. **Heartbeat for long tasks** - Report progress
5. **Error handling** - Distinguish retryable vs non-retryable

### Common Pitfalls

**Workflow Violations**:

- Using `datetime.now()` instead of `workflow.now()`
- Threading or async operations in workflow code
- Calling external APIs directly from workflow
- Non-deterministic logic in workflows

**Activity Mistakes**:

- Non-idempotent operations (can't handle retries)
- Missing timeouts (activities run forever)
- No error classification (retry validation errors)
- Ignoring payload limits (2MB per argument)

### Operational Considerations

**Monitoring**:

- Workflow execution duration
- Activity failure rates
- Retry attempts and backoff
- Pending workflow counts

**Scalability**:

- Horizontal scaling with workers
- Task queue partitioning
- Child workflow decomposition
- Activity batching when appropriate

## Additional Resources

**Official Documentation**:

- Temporal Core Concepts: docs.temporal.io/workflows
- Workflow Patterns: docs.temporal.io/evaluate/use-cases-design-patterns
- Best Practices: docs.temporal.io/develop/best-practices
- Saga Pattern: temporal.io/blog/saga-pattern-made-easy

**Key Principles**:

1. Workflows = orchestration, Activities = external calls
2. Determinism is non-negotiable for workflows
3. Idempotency is critical for activities
4. State preservation is automatic
5. Design for failure and recovery

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: workflow-patterns
description: Use this skill when implementing tasks according to Conductor's TDD workflow, handling phase checkpoints, managing git commits for tasks, or understanding the verification protocol.
risk: safe
source: community
date_added: '2026-02-27'
---

# Workflow Patterns

Guide for implementing tasks using Conductor's TDD workflow, managing phase checkpoints, handling git commits, and executing the verification protocol that ensures quality throughout implementation.

## Use this skill when

- Implementing tasks from a track's plan.md
- Following TDD red-green-refactor cycle
- Completing phase checkpoints
- Managing git commits and notes
- Understanding quality assurance gates
- Handling verification protocols
- Recording progress in plan files

## Do not use this skill when

- The task is unrelated to workflow patterns
- You need a different domain or tool outside this scope

## Instructions

- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
- If detailed examples are required, open `resources/implementation-playbook.md`.

## Resources

- `resources/implementation-playbook.md` for detailed patterns and examples.

## Limitations
- Use this skill only when the task clearly matches the scope described above.
- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.


---
name: workorai
description: "WorkorAI talent-marketplace skill: candidates search jobs and manage applications; employers run the job lifecycle and get ranked candidate matches with white-box fit explanations."
category: productivity
risk: critical
source: community
source_repo: work0r-ai/agent-kit
source_type: community
date_added: "2026-07-03"
author: work0r-ai
tags: [job-search, hiring, recruiting, talent-marketplace, mcp]
tools: [claude, cursor, gemini]
license: "MIT"
license_source: "https://github.com/work0r-ai/agent-kit/blob/main/skills/workorai/LICENSE.txt"
---

# WorkorAI

## Overview

WorkorAI is a talent marketplace exposed to agents through an MCP server
(streamable HTTP at https://workorai.com/mcp, listed on the official MCP
Registry as `io.github.work0r-ai/workorai`). This skill routes requests by
intent across the dual-role tool surface: 9 `candidate.*` tools (job search,
job detail, applications, apply, invitations, saved jobs) and the
`employer.*` tools (job lifecycle, candidate discovery, invitations,
applicant review). Employer candidate discovery returns tiered rankings
(best/good/weak) with a white-box match explanation per candidate — fit
score, skills proven in interview, gaps, and a quotable rationale — instead
of a black-box score.

## When to Use This Skill

- Use when a user asks to find a job, search vacancies, apply to a position,
  or track their applications ("find me a job", "ищу работу").
- Use when an employer wants to post, publish, update, close, or archive a
  job on WorkorAI.
- Use when an employer asks to find, rank, compare, or evaluate candidates,
  or asks why a candidate matches a role.
- Use when a user needs to set up or troubleshoot the WorkorAI MCP
  connection and API key onboarding.

## How It Works

### Step 1: Connect the MCP server

Add the WorkorAI MCP server to your agent's MCP configuration. For Claude
Code:

```bash
claude mcp add --transport http workorai https://workorai.com/mcp
```

If the user has no API key yet, call the `request_access` tool and follow
the onboarding it returns.

### Step 2: Route by role and intent

Detect whether the request is a candidate flow or an employer flow, then use
the matching tool group:

- Candidate: `candidate.search_jobs`, `candidate.get_job`,
  `candidate.apply_to_job`, `candidate.get_applications`,
  `candidate.accept_invitation` / `candidate.decline_invitation`,
  `candidate.withdraw_application`, `candidate.set_saved_job`,
  `candidate.get_saved_jobs`.
- Employer: `employer.create_job` → `employer.publish_job` →
  `employer.close_job` / `employer.archive_job` for the lifecycle;
  `employer.search_candidates_for_job` or
  `employer.search_candidates_by_query` for discovery;
  `employer.invite_candidate`, `employer.list_applicants`,
  `employer.get_applicant_detail`, `employer.set_review_status` for
  pipeline work.

### Step 3: Explain matches with white-box data

When presenting employer search results, keep the tier structure
(best/good/weak) and surface each candidate's `matchExplanation`: fit score,
interview-proven skills, gaps, and rationale. For deeper comparison, fetch
per-candidate interview evidence with `employer.get_candidate_evidence` and
`employer.get_applicant_transcript`.

## Examples

### Example 1: Candidate job search

```
User: "Find me remote TypeScript jobs and apply to the best one."
Agent: candidate.search_jobs(query="TypeScript", remote=true)
       → present ranked results → candidate.get_job(id)
       → confirm with the user → candidate.apply_to_job(id)
```

### Example 2: Employer candidate discovery

```
User: "Who are the best candidates for my Senior Backend role?"
Agent: employer.search_candidates_for_job(jobId)
       → report Best tier with each candidate's fit score, proven
         skills, and gaps → employer.invite_candidate on approval
```

## Best Practices

- ✅ Confirm with the user before applying, inviting, or changing job
  status — these are visible, stateful marketplace actions.
- ✅ Quote the white-box match explanation when recommending a candidate,
  so the employer sees why, not just a score.
- ✅ Use `request_access` for key onboarding instead of asking users to
  paste credentials into chat.
- ❌ Don't fabricate fit scores or ranks — only report what the tools
  return.
- ❌ Don't apply to jobs or send invitations in bulk without explicit
  user approval.

## Limitations

- Requires a WorkorAI account and API key; tools fail without a valid key.
- This skill does not replace environment-specific validation, testing, or
  expert review.
- Stop and ask for clarification if required inputs, permissions, or safety
  boundaries are missing.

## Security & Safety Notes

- All operations go through the remote WorkorAI MCP server over HTTPS; the
  skill itself runs no shell commands.
- Mutating tools (apply, withdraw, invite, publish, close, delete) should
  be preceded by an explicit user confirmation.
- Treat API keys as secrets: store them in MCP client configuration, never
  in chat transcripts or committed files.

## Additional Resources

- [Source repository](https://github.com/work0r-ai/agent-kit) — full skill
  with reference files and agents (npm: `@workorai/agent-kit`)
- [WorkorAI MCP endpoint](https://workorai.com/mcp)


---
name: "wp-guard"
description: "Review generated or changed WordPress plugins, themes, and blocks for security, internationalization, performance, and API correctness."
risk: "offensive"
source: "community"
source_repo: "amElnagdy/guard-skills"
source_type: "community"
date_added: 2026-07-13
author: "community"
tags: []
tools: []
---

> **⚠ AUTHORIZED USE ONLY**
> This skill is for educational purposes or authorized security assessments only.
> You must have explicit, written permission from the system owner before using this tool.
> Misuse of this tool is illegal and strictly prohibited.

> **Mandatory confirmation gate**
> Before running any command that probes, exploits, changes, persists on, extracts data from, or attempts credential access against a target:
> 1. Ask the user to state the exact target URL, IP, account, or resource.
> 2. Ask the user to confirm written authorization and the permitted scope.
> 3. Show the exact command(s) and explain their expected effect.
> 4. Wait for explicit confirmation in the current conversation.
>
> Without that confirmation, remain read-only and provide defensive guidance only. Prefer a sandbox, disposable VM, or controlled lab.

# WP Guard

> [!WARNING]
> **Authorized Use Only.** Review only WordPress code and environments the user owns or is explicitly authorized to assess. Keep checks non-destructive and inside the approved scope.

You are reviewing generated or changed WordPress code before it ships. Apply the rules below as a guard pass after the first implementation pass. Be a sharp reviewer, not a pedantic one: flag what creates vulnerabilities, breaks translations, or melts servers — ignore cosmetic preferences WPCS tooling already handles.

These rules exist because AI agents produce WordPress code with systematic failures: raw `echo` of request data, AJAX handlers with neither nonce nor capability check, SQL built by string interpolation, English hardcoded into user-facing strings, `posts_per_page => -1` on sites with a million posts, and hand-rolled replacements for APIs core already ships. Each one looks fine in a demo and fails in production.

## When to Use

Use this skill when reviewing generated or changed WordPress code — plugins, themes, and blocks — before it ships. Activate it reactively after an agent writes, edits, or reviews code touching WordPress APIs: hooks, custom post types, REST endpoints, database queries, and block editor integrations.

## How to use this skill

**Guard-pass mode** (recommended): after WordPress code has been generated or edited, apply the rules to the diff or target files, then run the self-check before delivery. Fix violations before showing the user.

**Live mode** (explicit): when the user invokes this skill before writing WordPress code, apply the same rules while writing, then run the self-check before delivery.

**Review mode** (the user asks you to review, audit, or rate WordPress code): walk [references/review-checklist.md](references/review-checklist.md) against the target files and produce a structured findings report. Do not edit code in review mode unless asked.

Pair this skill with clean-code-guard when both are installed: clean-code-guard owns generic code quality; wp-guard owns the WordPress layer.

## Adapt to the project first

1. Read the project's agent instructions (CLAUDE.md, AGENTS.md), `phpcs.xml`/WPCS config, and `composer.json`. Project conventions win on conflict.
2. Identify the established prefix (functions, options, meta keys, handles) and the minimum supported WP/PHP versions. Match both.
3. Detect context: WooCommerce APIs in play → apply woo-guard alongside this skill when it is installed; otherwise apply WooCommerce's HPOS, CRUD, and checkout rules from its developer documentation. Multilingual site (WPML/Polylang/multisite) → i18n rules are blocking, not advisory.
4. Read one neighboring file before writing. Mirror its error handling, hook registration style, and escaping habits — unless they violate the security rules below, which are non-negotiable.

## The Rules

### Security — must fix, no exceptions

1. **Escape late, escape everything.** Every variable crossing into HTML output goes through the context-correct function: `esc_html()`, `esc_attr()`, `esc_url()`, or `wp_kses()`/`wp_kses_post()` for rich content. Data passed to inline JS goes through `wp_json_encode()` + `wp_add_inline_script()` — `esc_js()` is legacy, for single-quoted strings in inline attributes only. Escaping happens at output, not at storage. `echo $anything;` without an `esc_*` wrapper fails review.

2. **Sanitize early, and unslash first.** Request data (`$_POST`, `$_GET`, `$_REQUEST`, `$_SERVER`) never touches logic raw: `wp_unslash()` first, then the type-correct sanitizer (`sanitize_text_field()`, `sanitize_key()`, `absint()`, `sanitize_email()`, …). Sanitization is not escaping; doing one never excuses the other.

3. **Every state change proves identity and intent.** Form handlers, AJAX endpoints, and REST routes that change anything require BOTH a capability check (`current_user_can()`) AND a nonce (`check_admin_referer()`, `check_ajax_referer()`, or REST nonce handling). A nonce is not authorization. A REST `permission_callback` of `__return_true` on a writing route fails review.

4. **`$wpdb->prepare()` for every query containing a variable.** Placeholders (`%s`, `%d`, `%f`, and `%i` for identifiers on WP ≥ 6.2), never interpolation or concatenation. Prefer `WP_Query`, the meta and options APIs over raw SQL when they can express the query.

### Core API discipline

5. **Use the platform; don't reinvent it.** Outbound HTTP via `wp_remote_get()`/`wp_remote_post()`, never curl. Assets via `wp_enqueue_script()`/`wp_enqueue_style()`, never echoed `<script>`/`<style>` tags. Scheduling via WP-Cron or Action Scheduler. Redirects via `wp_safe_redirect()` followed by `exit`. File writes via `WP_Filesystem`. Simple persistent data via options/transients, not a custom table.

6. **Verify every hook and function exists.** Before `add_action()`, `add_filter()`, or calling a core/plugin function, confirm it exists in the supported versions — read the source or the project's installed code. Hallucinated hooks fail silently in WordPress: no error, no behavior. Also match the hook to the moment — front-end code does not load on `admin_init`, queries do not run before `init` expects them.

7. **Prefix or namespace everything public.** Functions, classes, options, transients, meta keys, script handles, AJAX actions, REST namespaces — all carry the project prefix. Generic names (`get_settings`, `data`, `api_key`) are collisions waiting for the next active plugin.

8. **Guard direct access.** Every PHP file that does work starts with the `ABSPATH` check (or equivalent project convention).

### Internationalization

9. **Every user-facing string is translation-ready.** The correct wrapper for the context (`__()`, `_e()`, `_x()`, `_n()`, or the escaping combos `esc_html__()`, `esc_attr__()`), a literal text domain matching the plugin slug — never a variable or constant — translator comments on every placeholder, `_n()` for plurals (never `sprintf` with a hardcoded singular/plural choice), and no sentence assembly by concatenation. Dates and numbers through `date_i18n()`/`wp_date()` and `number_format_i18n()`. Details and JS i18n: [references/i18n.md](references/i18n.md).

### Performance

10. **Query discipline.** No `posts_per_page => -1` and no `query_posts()`, ever. Use `'fields' => 'ids'` when only IDs are needed, `'no_found_rows' => true` when not paginating, and never query inside a loop what could be primed once (meta/term caches). Details: [references/performance.md](references/performance.md).

11. **Cache expensive work, load assets where used.** Remote calls and heavy computations go behind transients or the object cache with a deliberate TTL. Options that are large or rarely read register with `autoload => false`. Scripts and styles enqueue only on the screens that use them.

## Self-check before delivery

1. Grep your diff for `echo`, `print`, `<?=`: is every variable output escaped with the context-correct function?
2. Grep for `$_POST`, `$_GET`, `$_REQUEST`: unslashed? sanitized? nonce-verified? capability-checked?
3. Grep for `$wpdb->`: every variable behind a placeholder?
4. Any user-facing string outside an i18n wrapper? Any non-literal text domain?
5. Any hook or function you did not verify exists?
6. Any unbounded query, uncached remote call, or unconditional enqueue?
7. Does every new public name carry the project prefix?
8. Would this survive WPCS (`WordPress-Extra` + `WordPress-Security`) without warnings you cannot justify?

If any answer is wrong, fix it before showing the user.

## Reporting format (review mode)

```
**Rule N violation** in `path/file.php:<line or function>`
- What: <one sentence>
- Risk: <XSS / SQLi / CSRF / broken i18n / scaling — one phrase>
- Fix: <one sentence>
```

Group by file, lead with security findings. If a file is clean, don't mention it.

## Severity guide

- **Must fix:** Rules 1–4 — these are exploitable (XSS, SQLi, CSRF, privilege escalation)
- **Should fix:** Rules 5–9 — conflicts, silent failures, untranslatable releases
- **Worth noting:** Rules 10–11 — they decide whether the code survives traffic; block on them for code that runs on every request

## References

- [references/security.md](references/security.md) — escaping/sanitization function tables, nonce lifecycle, REST permissions, `$wpdb->prepare` details, file uploads
- [references/i18n.md](references/i18n.md) — wrapper selection, text domain rules, plurals, translator comments, JS translations, RTL, multilingual-plugin gotchas
- [references/performance.md](references/performance.md) — WP_Query flags, transients vs object cache, autoload hygiene, asset loading, cron, scaling traps
- [references/review-checklist.md](references/review-checklist.md) — structured walk-through for review mode
- [references/sources.md](references/sources.md) — handbook and research URLs; read only when citing a source

## What this skill does not do

- Run PHPCS, PHPStan, or Plugin Check — use the project's tooling for mechanical verification; this skill is the judgment layer above it.
- Decide plugin architecture or business logic — it guards how WordPress code ships, not what it does.
- Replace clean-code-guard or test-guard — generic code quality and test quality remain their jurisdiction.