Files
wp-agentic-writer/DEFECT_REPORT_IMAGE_GENERATION.md
Dwindi Ramadhana d2c10756ab Add AI writing assistant plugin with local backend, brave search, and image generation support
- Implement local backend AI provider with Ollama integration
- Add Brave Search API integration for real-time search suggestions
- Add image generation manager with multiple AI providers
- Create hybrid provider system with local/cloud fallback
- Add comprehensive settings UI with provider management
- Implement Gutenberg sidebar with writing assistance controls
- Add SEO schema generation for AI-generated content
- Multiple provider support: OpenRouter, local backend, Codex
2026-05-17 10:48:05 +07:00

14 KiB

WP Agentic Writer - Defect Report

Date: January 29, 2026
Reporter: Development Team
Testing Session: Image Generation Feature Integration


Executive Summary

After comprehensive flow tracing, 4 critical defects and multiple integration gaps were identified. The image generation backend is functional, but frontend integration is incomplete.


Defect #1: "Create Outline Now" Button - Mode Timing Issue

Symptom

Clicking "Create Outline Now" only prefills English message and changes mode. User expects automatic outline generation.

Root Cause Analysis

File: @/Users/dwindown/Local Sites/bricks/app/public/wp-content/plugins/wp-agentic-writer/assets/js/sidebar.js:4432-4444

onClick: async () => {
    setAgentMode('planning');  // Line 4434
    const outlineMessage = 'Create an outline based on our discussion';
    setInput(outlineMessage);  // Line 4438
    setTimeout(() => {
        sendMessage();  // Line 4443
    }, 100);
}

Problem: React's setState is asynchronous. When sendMessage() is called 100ms later:

  1. agentMode state may not have updated yet in the closure
  2. input state may not have updated yet
  3. The sendMessage() function reads stale state values

Flow Trace:

User clicks "Create Outline Now"
    ↓
setAgentMode('planning') called - state update QUEUED
    ↓
setInput('Create an outline...') called - state update QUEUED  
    ↓
100ms timeout fires
    ↓
sendMessage() runs with STALE state (agentMode might still be 'chat')
    ↓
Line 3084: if (agentMode === 'chat' && !hasMentions) → TRUE (stale state!)
    ↓
Chat API called instead of generate-plan

Expected Behavior

Button should directly trigger planning flow with proper mode context, bypassing React state timing issues.

Pass mode and message directly to sendMessage, not relying on state:

onClick: async () => {
    setAgentMode('planning');
    const outlineMessage = 'Create an outline based on our discussion';
    
    // Call API directly instead of relying on state
    await triggerPlanGeneration(outlineMessage, {
        mode: 'planning',
        autoTrigger: true
    });
}

Or use a dedicated function that doesn't depend on agentMode state.


Defect #2: Clarity Check Not Triggered for Planning Mode

Symptom

Cost tracking shows clarity_check was never called when using "Create Outline Now".

Root Cause Analysis

Flow Trace through sendMessage():

Line 3049: shouldShowPlan = (agentMode === 'planning')

If agentMode is still 'chat' (due to Defect #1):
    Line 3084: if (agentMode === 'chat' && !hasMentions) → TRUE
        → Enters CHAT flow (NOT planning flow)
        → Calls /chat API
        → Clarity check is NOT in this branch

If agentMode correctly updated to 'planning':

Line 3077: if (agentMode === 'planning' && !hasMentions && currentPlanRef.current)
    → FALSE because currentPlanRef.current is null (no existing plan)
    → Falls through

Line 3084: if (agentMode === 'chat' && !hasMentions)
    → FALSE because agentMode is 'planning'
    → Falls through

Line 3225: if (!hasMentions && refineableBlocks.length > 0)
    → FALSE if no content exists yet
    → Falls through

Line 3262: if (!hasMentions)
    → TRUE
    → Enters clarity check + generate-plan flow ✓

Conclusion: The clarity check SHOULD work if agentMode is correctly set to 'planning'. The root cause is Defect #1 - the timing issue with state updates.

Fix Defect #1, which will automatically fix this defect.


Defect #3: Numbered List with Bold Title + Bullets - Incorrect Conversion

Symptom

Markdown like:

1. **Jadikan AI sebagai Asisten**
- Gunakan untuk mempercepat pekerjaan
- Manfaatkan sebagai sumber referensi

1. **Terus Belajar dan Beradaptasi**
- Ikuti perkembangan teknologi AI

Renders as:

  • Ordered list with item "1. Jadikan AI sebagai Asisten"
  • Separate unordered list with bullets
  • New ordered list restarting at "1." for next section

User sees "1. 1. 1." instead of "1. 2. 3."

Root Cause Analysis

File: @/Users/dwindown/Local Sites/bricks/app/public/wp-content/plugins/wp-agentic-writer/includes/class-markdown-parser.php:261-274

// Handle ordered lists.
if ( preg_match( '/^\d+\.\s+(.+)$/', $trimmed, $matches ) ) {
    // ... creates ordered list item
    $list_items[] = self::parse_inline_markdown( $matches[1] );
    continue;
}

Problem: The parser correctly identifies numbered items, but when an empty line or different list type appears, it flushes the current list. Each section becomes a separate ordered list block, each starting at 1.

The merge_consecutive_ordered_lists() function at line 674 only merges consecutive ordered lists. But the structure has:

ordered list (1 item)
unordered list (bullets)
ordered list (1 item)  ← NOT consecutive, won't merge
unordered list (bullets)

Expected Behavior (per user request)

For numbered items with bold titles followed by bullet sub-content:

1. **Bold Title**        → core/paragraph with "1. <strong>Bold Title</strong>"
- bullet item            → core/list (unordered)
- bullet item

2. **Next Title**        → core/paragraph with "2. <strong>Next Title</strong>"
- more bullets           → core/list (unordered)

This structure:

  • Prevents the "1. 1. 1." numbering issue
  • Creates logical grouping
  • Maintains proper section hierarchy

Option A: Detect pattern ^\d+\.\s+\*\*(.+)\*\*$ (numbered + bold) and treat as paragraph:

// Handle numbered items with bold title (treat as paragraph, not list)
if ( preg_match( '/^(\d+)\.\s+\*\*(.+)\*\*\s*$/', $trimmed, $matches ) ) {
    // Create paragraph with manual numbering
    $content = $matches[1] . '. <strong>' . self::parse_inline_markdown( $matches[2] ) . '</strong>';
    $blocks[] = self::create_paragraph_block( $content );
    continue;
}

Option B: Pre-process markdown to normalize this pattern before parsing.


Defect #4: Image Blocks Missing data-agent-image-id Attribute

Symptom

Generated image blocks have no way to:

  1. Confirm agent assigned an image ID
  2. View the recommended prompt/alt text
  3. Trigger image generation modal
  4. Connect to backend image recommendations

Root Cause Analysis

File: @/Users/dwindown/Local Sites/bricks/app/public/wp-content/plugins/wp-agentic-writer/includes/class-markdown-parser.php:644-664

private static function create_image_placeholder_block( $description ) {
    $alt = trim( $description );
    $attrs = array(
        'id' => 0,
        'url' => '',
        'alt' => $alt,
        'caption' => '',
        'sizeSlug' => 'large',
        'linkDestination' => 'none',
    );
    // ❌ MISSING: 'data-agent-image-id' => 'img_xxx'

The data-agent-image-id attribute is documented in:

  • IMAGE_GENERATION_IMPLEMENTATION_PLAN.md
  • IMAGE_GENERATION_README.md
  • image-gen-flow.md
  • image-modal.js (expects this attribute)

But NEVER implemented in the actual code!

Missing Integration Points

  1. Markdown Parser: Must generate unique agent_image_id and add to block attrs
  2. Backend Storage: Must save recommendations with matching IDs to wp_wpaw_images table
  3. Block Toolbar: Must add "Generate Image" button for image blocks with this attribute
  4. Modal Trigger: Must open image modal after article generation or from toolbar

Step 1: Update create_image_placeholder_block():

private static function create_image_placeholder_block( $description, $image_index = 0 ) {
    $alt = trim( $description );
    $agent_image_id = 'img_' . uniqid();  // Or use index-based ID
    
    $attrs = array(
        'id' => 0,
        'url' => '',
        'alt' => $alt,
        'caption' => '',
        'sizeSlug' => 'large',
        'linkDestination' => 'none',
        'data-agent-image-id' => $agent_image_id,
    );
    // ...
}

Step 2: Track and return image IDs during article generation

Step 3: Register toolbar button for image blocks (see below)


Missing Integration #1: Image Block Toolbar Button

Current State

No "Generate Image" button exists in image block toolbar.

Required Implementation

File to create: Extend block-refine.js or create new block-image-generate.js

// Add toolbar button to core/image blocks with data-agent-image-id
const withImageGenerateToolbar = createHigherOrderComponent((BlockEdit) => {
    return (props) => {
        const { clientId } = props;
        const block = useSelect(
            (select) => select('core/block-editor').getBlock(clientId),
            [clientId]
        );
        
        if (!block || block.name !== 'core/image') {
            return wp.element.createElement(BlockEdit, props);
        }
        
        const agentImageId = block.attributes['data-agent-image-id'];
        if (!agentImageId) {
            return wp.element.createElement(BlockEdit, props);
        }
        
        const openImageModal = () => {
            window.dispatchEvent(
                new CustomEvent('wpaw:open-image-modal', {
                    detail: { agentImageId, blockId: clientId }
                })
            );
        };
        
        return wp.element.createElement(
            wp.element.Fragment,
            null,
            wp.element.createElement(BlockEdit, props),
            wp.element.createElement(
                BlockControls,
                null,
                wp.element.createElement(
                    ToolbarGroup,
                    null,
                    wp.element.createElement(ToolbarButton, {
                        icon: 'format-image',
                        label: 'Generate AI Image',
                        onClick: openImageModal,
                    })
                )
            )
        );
    };
}, 'withImageGenerateToolbar');

addFilter(
    'editor.BlockEdit',
    'wp-agentic-writer/image-generate-toolbar',
    withImageGenerateToolbar
);

Missing Integration #2: Image Modal Trigger After Article Generation

Current State

image-modal.js component exists but is never rendered/triggered.

Required Implementation

In sidebar.js, after article execution completes:

// After all sections are written and blocks inserted:
const checkForImagePlaceholders = () => {
    const blocks = wp.data.select('core/block-editor').getBlocks();
    const imagePlaceholders = blocks.filter(
        block => block.name === 'core/image' && 
                 block.attributes['data-agent-image-id']
    );
    
    if (imagePlaceholders.length > 0) {
        // Open image review modal
        window.dispatchEvent(
            new CustomEvent('wpaw:open-image-review-modal', {
                detail: { 
                    postId: postId,
                    imageCount: imagePlaceholders.length 
                }
            })
        );
    }
};

In image-modal.js, listen for event:

useEffect(() => {
    const handleOpenModal = (event) => {
        setPostId(event.detail.postId);
        setIsOpen(true);
        loadRecommendations(event.detail.postId);
    };
    
    window.addEventListener('wpaw:open-image-review-modal', handleOpenModal);
    return () => window.removeEventListener('wpaw:open-image-review-modal', handleOpenModal);
}, []);

Missing Integration #3: Backend Image ID Generation

Current State

[IMAGE: description] placeholders are converted to blocks, but:

  • No unique ID generated
  • No storage in wp_wpaw_images table during article generation
  • No link between block and database record

Required Implementation

During article generation in class-gutenberg-sidebar.php:

  1. Parse [IMAGE: ...] placeholders before block conversion
  2. Generate unique agent_image_id for each
  3. Store in wp_wpaw_images table with post_id, prompt, alt_text
  4. Pass image IDs to markdown parser for block attribute injection
// In handle_generate_article or handle_execute_plan:
$image_placeholders = [];
preg_match_all('/\[IMAGE:\s*(.+?)\]/i', $markdown_content, $matches);

foreach ($matches[1] as $index => $description) {
    $agent_image_id = 'img_' . $post_id . '_' . ($index + 1);
    $image_placeholders[] = [
        'agent_image_id' => $agent_image_id,
        'description' => $description,
    ];
    
    // Save to database
    $image_manager = WP_Agentic_Writer_Image_Manager::get_instance();
    // ... save recommendation
}

// Convert markdown with image IDs
$blocks = WP_Agentic_Writer_Markdown_Parser::to_blocks($markdown_content, $image_placeholders);

Priority Matrix

Defect Severity Impact Fix Effort
#1 - Create Outline timing High Blocks main workflow Low
#2 - Clarity check High Poor content quality Depends on #1
#3 - Numbered list Medium Visual formatting Medium
#4 - Image IDs missing Critical Image feature broken Medium
Toolbar button Critical No way to trigger images Medium
Modal trigger Critical No user-facing image feature Medium
Backend ID generation Critical No data persistence Medium

  1. Defect #1 - Fix timing issue (enables #2)
  2. Defect #4 + Backend ID generation - Core image functionality
  3. Toolbar button - User can trigger image generation
  4. Modal trigger - Automatic flow after article generation
  5. Defect #3 - Formatting improvement (lower priority)

Testing Checklist After Fixes

  • Click "Create Outline Now" → Clarity quiz appears (if needed)
  • Click "Create Outline Now" → Plan generated automatically
  • Cost tracking shows clarity_check action
  • Numbered + bold items render as paragraphs with manual numbering
  • Image blocks have data-agent-image-id attribute in inspector
  • Image blocks show "Generate AI Image" in toolbar
  • After article generation, image modal opens automatically
  • Can generate variants for each image placeholder
  • Can select and commit variant to Media Library
  • Block updates with real image after commit

Report Status: Complete
Next Steps: Implement fixes in priority order