# 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` ```javascript 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. ### Recommended Fix Pass mode and message directly to sendMessage, not relying on state: ```javascript 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. ### Recommended Fix Fix Defect #1, which will automatically fix this defect. --- ## Defect #3: Numbered List with Bold Title + Bullets - Incorrect Conversion ### Symptom Markdown like: ```markdown 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` ```php // 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. Bold Title" - bullet item → core/list (unordered) - bullet item 2. **Next Title** → core/paragraph with "2. Next Title" - more bullets → core/list (unordered) ``` This structure: - Prevents the "1. 1. 1." numbering issue - Creates logical grouping - Maintains proper section hierarchy ### Recommended Fix **Option A:** Detect pattern `^\d+\.\s+\*\*(.+)\*\*$` (numbered + bold) and treat as paragraph: ```php // 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] . '. ' . self::parse_inline_markdown( $matches[2] ) . ''; $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` ```php 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 ### Recommended Fix **Step 1:** Update `create_image_placeholder_block()`: ```php 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` ```javascript // 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:** ```javascript // 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:** ```javascript 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 ```php // 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 | --- ## Recommended Fix Order 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