# WP Agentic Writer Sidebar 1:1 Migration Plan **Source of truth:** `assets/js/sidebar.js` **Source length:** 12,363 lines **Scope:** planning/audit document only. No implementation code, no build step, no inferred behavior. This document exists to make the migration match `sidebar.js` exactly. If this file, `MIGRATION_GUIDE.md`, comments, or memory disagree with `assets/js/sidebar.js`, `assets/js/sidebar.js` wins. ## Non-Negotiable Rules 1. Preserve every behavior from `assets/js/sidebar.js` before extracting or improving anything. 2. Convert `wp.element.createElement(...)` to JSX mechanically only after copying the same source range. 3. Preserve hook order, state names, ref names, default values, dependency arrays, effect cleanups, and callback boundaries. 4. Preserve all `wpAgenticWriter` globals, endpoint paths, request bodies, headers, nonces, stream handling, abort handling, and error formatting. 5. Preserve all Gutenberg APIs: `registerPlugin`, `PluginSidebarMoreMenuItem`, `PluginSidebar`, `Panel`, `TextareaControl`, `TextControl`, `CheckboxControl`, `Button`, `RawHTML`, `dispatch`, `select`, and `wp.data.withSelect`. 6. Preserve all DOM tags, component tags, `className` values, dynamic class branches, `role`, `aria-*`, `title`, `placeholder`, `style`, `dangerouslySetInnerHTML`, button labels, visible text, icons, SVG markup, and conditional render gates. 7. Preserve editor block attribute class mutations, especially `wpaw-diff-added` and `wpaw-diff-removed`; these are migration-critical even though they are not sidebar wrapper classes. 8. Do not rename functions, split files, normalize copy, deduplicate logic, replace SVGs, replace `RawHTML`, or change UX flow during the first migration pass. 9. Extraction is allowed only after a monolithic JSX port can be checked against this document line range by line range. ## File-Level Boundaries | Lines | Required migration unit | | --- | --- | | 1-6 | File header comment. Preserve package context if the migrated file keeps source banner comments. | | 7-15 | IIFE argument and WordPress dependency destructuring. New module imports may replace destructuring only if every dependency maps 1:1. | | 16-30 | Debug logger and `isDebug` behavior. | | 31-35 | `pluginIcon` image element with `wpAgenticWriter.pluginUrl + "/assets/img/icon.svg"`, alt text, and 20px style. | | 37-12347 | `AgenticWriterSidebar` component. | | 12349-12352 | `mapSelectToProps`, selecting `core/editor`. | | 12355-12356 | `ConnectedSidebar = wp.data.withSelect(mapSelectToProps)(AgenticWriterSidebar)`. | | 12358-12362 | `registerPlugin("wp-agentic-writer", { icon: pluginIcon, render: ConnectedSidebar })`. | | 12363 | IIFE close with `window.wp`. | ## Migration Method 1. Create the new JSX target as a monolith first. 2. Copy ranges in the same order as the coverage table below. 3. Convert element calls mechanically: - tag/component name stays the same - prop names stay the same - children order stays the same - conditional gates stay in the same location - spread/rest behavior is not introduced unless already present in the source range 4. After the monolith is complete, compare it against this document: - every range is present - every function exists - every state/ref/effect exists in the same hook order - every class in the class inventory exists - every endpoint in the endpoint inventory exists - every render surface exists with the same branches 5. Only after the monolith is proven equivalent, optional extraction may start. Extraction must move code, not rewrite behavior. ## Component-Level Coverage ### State and Refs, Lines 40-366 | Lines | Kind | Name | | --- | --- | --- | | 40-41 | const | `settings` | | 42-138 | const | `formatAiErrorMessage` | | 139-141 | state | `[activeTab, setActiveTab]` | | 142-142 | state | `[messages, setMessages]` | | 143-143 | state | `[input, setInput]` | | 144-144 | state | `[isLoading, setIsLoading]` | | 145-145 | state | `[currentSessionId, setCurrentSessionId]` | | 146-146 | state | `[availableSessions, setAvailableSessions]` | | 147-148 | state | `[isSessionActionLoading, setIsSessionActionLoading]` | | 149-151 | state | `[agentMode, setAgentMode]` | | 152-154 | const/ref | `tabIdRef` | | 155-159 | state | `[sessionLock, setSessionLock]` | | 160-162 | const/ref | `lockHeartbeatRef` | | 163-181 | const/memo | `defaultPostConfig` | | 182-182 | state | `[postConfig, setPostConfig]` | | 183-183 | state | `[isConfigLoading, setIsConfigLoading]` | | 184-184 | state | `[isConfigSaving, setIsConfigSaving]` | | 185-185 | state | `[configError, setConfigError]` | | 186-186 | const/ref | `configHydratedRef` | | 187-187 | const/ref | `lastSavedConfigRef` | | 188-190 | const/ref | `configSaveTimeoutRef` | | 191-195 | state | `[cost, setCost]` | | 196-200 | state | `[monthlyBudget, setMonthlyBudget]` | | 201-203 | state | `[providerInfo, setProviderInfo]` | | 204-223 | const | `applyProviderMetadata` | | 224-224 | state | `[isEditorLocked, setIsEditorLocked]` | | 225-225 | state | `[isRefinementLocked, setIsRefinementLocked]` | | 226-226 | state | `[refiningBlockIds, setRefiningBlockIds]` | | 227-227 | const/ref | `refinementDecoratedIdsRef` | | 228-228 | const/ref | `lockedEditableNodesRef` | | 229-229 | const/ref | `lockedBlockIdsRef` | | 230-230 | const | `REFINEMENT_ALL_CONFIRM_THRESHOLD` | | 231-235 | state | `[refineAllConfirm, setRefineAllConfirm]` | | 236-236 | const/ref | `refineAllConfirmResolverRef` | | 237-239 | const/ref | `skipRefineAllConfirmRef` | | 240-240 | state | `[seoAudit, setSeoAudit]` | | 241-241 | state | `[isSeoAuditing, setIsSeoAuditing]` | | 242-242 | state | `[isGeneratingMeta, setIsGeneratingMeta]` | | 243-245 | state | `[activeSeoFixKey, setActiveSeoFixKey]` | | 246-246 | state | `[inClarification, setInClarification]` | | 247-247 | state | `[questions, setQuestions]` | | 248-248 | state | `[currentQuestionIndex, setCurrentQuestionIndex]` | | 249-249 | state | `[answers, setAnswers]` | | 250-250 | state | `[detectedLanguage, setDetectedLanguage]` | | 251-252 | state | `[clarificationMode, setClarificationMode]` | | 253-253 | state | `[pendingRefinement, setPendingRefinement]` | | 254-254 | state | `[pendingEditPlan, setPendingEditPlan]` | | 255-255 | state | `[pendingDiffBlockIds, setPendingDiffBlockIds]` | | 256-256 | const/ref | `lastGenerationRequestRef` | | 257-257 | const/ref | `currentPlanRef` | | 258-258 | const/ref | `lastExecuteRequestRef` | | 259-259 | const/ref | `sectionInsertIndexRef` | | 260-260 | const/ref | `activeSectionIdRef` | | 261-261 | const/ref | `sectionBlocksRef` | | 262-262 | const/ref | `blockSectionRef` | | 263-263 | const/ref | `markdownRendererRef` | | 264-264 | const/ref | `lastRefineRequestRef` | | 265-265 | const/ref | `lastChatRequestRef` | | 266-266 | const/ref | `stopExecutionRef` | | 267-267 | const/ref | `activeAbortControllerRef` | | 268-268 | const/ref | `activeReaderRef` | | 269-273 | const/ref | `activeOperationRef` | | 274-274 | state | `[executionStopped, setExecutionStopped]` | | 275-279 | state | `[activeOperation, setActiveOperation]` | | 280-287 | state | `[writingState, setWritingState]` | | 288-289 | state | `[isWritingStateLoading, setIsWritingStateLoading]` | | 290-295 | state | `[workspaceSnapshot, setWorkspaceSnapshot]` | | 296-307 | state | `[isWorkspaceCollapsed, setIsWorkspaceCollapsed]` | | 308-323 | const | `toggleAgentWorkspace` | | 324-325 | state | `[showMentionAutocomplete, setShowMentionAutocomplete]` | | 326-326 | state | `[mentionQuery, setMentionQuery]` | | 327-327 | state | `[mentionOptions, setMentionOptions]` | | 328-328 | state | `[mentionCursorIndex, setMentionCursorIndex]` | | 329-330 | state | `[showSlashAutocomplete, setShowSlashAutocomplete]` | | 331-331 | state | `[slashQuery, setSlashQuery]` | | 332-332 | state | `[slashOptions, setSlashOptions]` | | 333-333 | state | `[slashCursorIndex, setSlashCursorIndex]` | | 334-334 | state | `[isTextareaExpanded, setIsTextareaExpanded]` | | 335-335 | const/ref | `inputRef` | | 336-338 | const/ref | `streamTargetRef` | | 339-340 | state | `[focusKeywordSuggestions, setFocusKeywordSuggestions]` | | 341-341 | state | `[selectedFocusKeyword, setSelectedFocusKeyword]` | | 342-343 | state | `[showCustomKeywordInput, setShowCustomKeywordInput]` | | 344-344 | state | `[customKeywordInput, setCustomKeywordInput]` | | 345-345 | const/ref | `messagesSaveTimeoutRef` | | 346-346 | const/ref | `lastPersistedMessagesRef` | | 347-349 | const/ref | `isHydratingSessionRef` | | 350-350 | state | `[showWelcome, setShowWelcome]` | | 351-351 | state | `[welcomeKeywordInput, setWelcomeKeywordInput]` | | 352-354 | state | `[welcomeStartMode, setWelcomeStartMode]` | | 355-355 | state | `[aiUndoStack, setAiUndoStack]` | | 356-358 | const | `MAX_UNDO_STACK` | | 359-365 | state | `[memantoRestore, setMemantoRestore]` | | 366-366 | const/ref | `memantoRestoreFetchedRef` | ### Effects, Timeline, Editor Locking, Config Helpers, Lines 367-1194 | Lines | Kind | Name | | --- | --- | --- | | 367-372 | effect | `useEffect@367` | | 373-401 | effect | `useEffect@373` | | 402-448 | const | `savePostConfig` | | 449-473 | effect | `useEffect@449` | | 474-499 | effect | `useEffect@474` | | 500-510 | const | `normalizeWritingState` | | 511-539 | const | `saveWritingState` | | 540-550 | const | `persistWritingStatePatch` | | 551-585 | effect | `useEffect@551` | | 586-586 | const/ref | `messagesEndRef` | | 587-589 | const/ref | `messagesContainerRef` | | 590-595 | effect | `useEffect@590` | | 596-597 | const | `progressRegex` | | 598-608 | const | `activeTimelineStatuses` | | 609-609 | const | `writingTimelineStatuses` | | 610-621 | const | `findLastActiveTimelineIndex` | | 622-636 | const | `deactivateActiveTimelineEntries` | | 637-659 | const | `updateOrCreateTimelineEntry` | | 660-673 | const | `addActivityTimeline` | | 674-682 | const | `setActiveOperationState` | | 683-691 | const | `beginAgentOperation` | | 692-700 | const | `finishAgentOperation` | | 701-721 | const | `markActiveOperationStopping` | | 722-724 | const | `isAbortError` | | 725-728 | const | `registerActiveReader` | | 729-742 | callback | `requestRefineAllConfirmation` | | 743-752 | callback | `resolveRefineAllConfirmation` | | 753-764 | const | `captureEditorSnapshot` | | 765-775 | const | `pushUndoSnapshot` | | 776-812 | const | `undoLastAiOperation` | | 813-832 | effect | `useEffect@813` | | 833-841 | effect | `useEffect@833` | | 842-889 | effect | `useEffect@842` | | 890-921 | effect | `useEffect@890` | | 922-981 | effect | `useEffect@922` | | 982-1019 | effect | `useEffect@982` | | 1020-1028 | const | `toTextValue` | | 1029-1031 | const | `updatePostConfig` | | 1032-1071 | const | `buildPostConfigFromAnswers` | | 1072-1079 | const | `handleFocusKeywordChange` | | 1080-1089 | const | `handleKeywordSelect` | | 1090-1137 | const | `extractFocusKeywordSuggestions` | | 1138-1142 | const | `extractFocusKeywordSuggestion` | | 1143-1153 | const | `addFocusKeywordSuggestion` | | 1154-1159 | const | `addFocusKeywordSuggestions` | | 1160-1168 | effect | `useEffect@1160` | | 1169-1175 | effect | `useEffect@1169` | | 1176-1194 | const | `handleWelcomeStart` | ### SEO, Workspace, Session, Locking, Lines 1195-2515 | Lines | Kind | Name | | --- | --- | --- | | 1195-1269 | const | `runSeoAudit` | | 1270-1308 | const | `buildSeoAuditFixInstruction` | | 1309-1310 | const | `getSeoFixKey` | | 1311-1318 | const | `getSeoAuditPatternCount` | | 1319-1322 | const | `formatCountLabel` | | 1323-1328 | const | `formatAuditPatternLabel` | | 1329-1348 | const | `buildAuditRefinementContext` | | 1349-1459 | const | `handleSeoAuditFix` | | 1460-1563 | const | `generateMetaDescription` | | 1564-1587 | const | `extractBlockPreview` | | 1588-1599 | const | `getBlockPreviewById` | | 1600-1638 | callback | `buildWorkspaceSnapshot` | | 1639-1661 | effect | `useEffect@1639` | | 1662-1668 | effect | `useEffect@1662` | | 1669-1682 | effect | `useEffect@1669` | | 1683-1686 | effect | `useEffect@1683` | | 1687-1702 | effect | `useEffect@1687` | | 1703-1716 | effect | `useEffect@1703` | | 1717-1754 | callback | `sanitizeMessagesForStorage` | | 1755-1781 | callback | `hydrateSessionStateFromMessages` | | 1782-1839 | callback | `persistSessionMessages` | | 1840-1840 | const/ref | `messagesRef` | | 1841-1845 | effect | `useEffect@1841` | | 1846-1889 | effect | `useEffect@1846` | | 1890-1926 | callback | `acquireSessionLock` | | 1927-1947 | callback | `releaseSessionLock` | | 1948-1961 | callback | `startLockHeartbeat` | | 1962-1969 | callback | `stopLockHeartbeat` | | 1970-1994 | effect | `useEffect@1970` | | 1995-2026 | callback | `takeOverSession` | | 2027-2072 | effect | `useEffect@2027` | | 2073-2213 | effect | `useEffect@2073` | | 2214-2241 | effect | `useEffect@2214` | | 2242-2300 | effect | `useEffect@2242` | | 2301-2397 | const | `loadPostSessions` | | 2398-2515 | const | `openSessionById` | ### Mentions, Commands, Planning, Agent Decisions, Lines 2516-4320 | Lines | Kind | Name | | --- | --- | --- | | 2516-2526 | const | `resolveStreamTarget` | | 2527-2536 | const | `normalizeMentionToken` | | 2537-2550 | const | `extractMentionsFromText` | | 2551-2560 | const | `stripMentionsFromText` | | 2561-2569 | const | `hasTitleMention` | | 2570-2689 | const | `handleTitleRefinement` | | 2690-2712 | const | `parseInsertCommand` | | 2713-2747 | const | `getSlashOptions` | | 2748-2758 | const | `getBlockIndex` | | 2759-2777 | const | `resolveTargetBlockId` | | 2778-2870 | const | `insertRefinementBlock` | | 2871-3188 | const | `streamGeneratePlan` | | 3189-3213 | const | `retryLastGeneration` | | 3214-3228 | const | `retryLastExecute` | | 3229-3257 | const | `retryLastRefinement` | | 3258-3473 | const | `retryLastChat` | | 3474-3534 | const | `createBlockFromPlan` | | 3535-3543 | const | `normalizePlanActions` | | 3544-3604 | const | `buildPlanPreviewItem` | | 3605-3611 | const | `normalizePlanSectionTitle` | | 3612-3622 | const | `upsertSectionBlock` | | 3623-3632 | const | `removeSectionBlock` | | 3633-3673 | const | `loadSectionBlocks` | | 3674-3696 | const | `saveSectionBlocks` | | 3697-3709 | const | `ensurePlanTasks` | | 3710-3743 | const | `getTargetedRefinementBlocks` | | 3744-3828 | const | `findBestPlanSectionMatch` | | 3829-3851 | const | `updatePlanSectionStatus` | | 3852-3893 | const | `findSectionInsertIndex` | | 3894-3906 | const | `shouldShowWritingEmptyState` | | 3907-3956 | const | `summarizeChatHistory` | | 3957-4007 | const | `detectUserIntent` | | 4008-4027 | const | `buildOptimizedContext` | | 4028-4067 | const | `handleResetCommand` | | 4068-4096 | const | `updateOrCreatePlanMessage` | | 4097-4156 | const | `suggestKeywordsFromPlan` | | 4157-4172 | callback | `buildChatHistoryPayload` | | 4173-4186 | callback | `getLastUserMessageText` | | 4187-4198 | const | `shouldSkipPlanningCompletion` | | 4199-4218 | const | `getPlanRuntimeSummary` | | 4219-4221 | const | `getPlanId` | | 4222-4260 | const | `classifyAgentIntent` | | 4261-4320 | const | `decideAgentAction` | ### Execution, Refinement, Block Context, Lines 4321-6388 | Lines | Kind | Name | | --- | --- | --- | | 4321-4768 | const | `executePlanFromCard` | | 4769-4794 | const | `handleStopExecution` | | 4795-4870 | const | `clearChatContext` | | 4871-4953 | const | `createBlocksFromSerialized` | | 4954-5056 | const | `reformatBlocks` | | 5057-5142 | const | `revisePlanFromPrompt` | | 5143-5240 | const | `applyEditPlan` | | 5241-5280 | const | `cancelEditPlan` | | 5281-5304 | const | `formatClarificationContext` | | 5305-5327 | effect | `useEffect@5305` | | 5328-5362 | const | `removeDuplicateHeadings` | | 5363-5390 | const | `getRefineableBlocks` | | 5391-5420 | const | `getListItemBlocks` | | 5421-5426 | const | `resolveExplicitListItem` | | 5427-5442 | const | `getParentListId` | | 5443-5453 | const | `getBlockContentForContext` | | 5454-5470 | const | `getHeadingContextForBlock` | | 5471-5494 | const | `getNearbyParagraphContext` | | 5495-5503 | const | `getContextFromMentions` | | 5504-5518 | const | `extractQuotedTermsFromMessage` | | 5519-5520 | const | `getAllTextRefineableBlocks` | | 5521-5533 | const | `selectLikelySlangBlocks` | | 5534-5537 | const | `isAiSlopRequest` | | 5538-5589 | const | `getAiSlopFindingsForBlock` | | 5590-5606 | const | `selectLikelyAiSlopBlocks` | | 5607-5622 | const | `buildContextBlocksForRefinement` | | 5623-5704 | const | `buildRefinementDiagnosis` | | 5705-5799 | const | `resolveBlockMentions` | | 5800-6388 | const | `handleChatRefinement` | ### Chat Input, Send, Clarification, Welcome, Workspace, Lines 6389-9996 | Lines | Kind | Name | | --- | --- | --- | | 6389-6455 | render | `renderRefineAllConfirmModal` | | 6456-6579 | const | `getMentionOptions` | | 6580-6612 | effect | `useEffect@6580` | | 6613-6652 | const | `handleInputChange` | | 6653-6701 | const | `handleKeyDown` | | 6702-6726 | const | `insertMention` | | 6727-6758 | const | `insertSlashCommand` | | 6759-8056 | const | `sendMessage` | | 8057-8476 | const | `submitAnswers` | | 8477-8829 | render | `renderClarification` | | 8830-8916 | const | `startNewConversation` | | 8917-8959 | const | `deleteConversationSession` | | 8960-8983 | const | `getSessionDisplayTitle` | | 8984-8993 | const | `getSessionContinuityLabel` | | 8994-9004 | const | `getSessionDebugMeta` | | 9005-9184 | render | `renderWelcomeScreen` | | 9185-9253 | render | `renderWritingEmptyState` | | 9254-9459 | render | `renderFocusKeywordBar` | | 9460-9629 | render | `renderAgentWorkspaceCard` | | 9630-9632 | alias | `renderContextIndicator = renderAgentWorkspaceCard` | | 9633-9996 | render/action | `renderContextualAction` | ### Messages, Tabs, Cost, Final Shell, Lines 9997-12363 | Lines | Kind | Name | | --- | --- | --- | | 9997-10917 | render | `renderMessages` | | 10918-11434 | render | `renderConfigTab` | | 11435-11448 | const | `getAgentStatus` | | 11449-11585 | render | `renderGlobalStatusBar` | | 11586-12020 | render | `renderChatTab` | | 12021-12022 | state | `[costHistory, setCostHistory]` | | 12023-12050 | const | `refreshCostData` | | 12051-12057 | effect | `useEffect@12051` | | 12058-12306 | render | `renderCostTab` | | 12307-12346 | return | component `Fragment` with menu item, sidebar, panel, and active tab renderer | | 12347 | close | `AgenticWriterSidebar` close | | 12349-12363 | boot | `mapSelectToProps`, `ConnectedSidebar`, `registerPlugin`, IIFE close | ## Render Surface Checklist Each render surface must be migrated as an element tree, not summarized. | Render surface | Lines | Required branches/elements | | --- | --- | --- | | `renderRefineAllConfirmModal` | 6389-6455 | Null when closed; dialog overlay; modal; title; body; `CheckboxControl`; cancel and continue `Button`s; session skip flag behavior. | | `renderClarification` | 8477-8829 | Null guard; `renderSingleChoice`; custom option textarea; `renderMultipleChoice`; `renderOpenText`; `renderConfigForm`; answer switch; quiz wrapper; progress bar; previous/skip/next-finish buttons. | | `renderWelcomeScreen` | 9005-9184 | Recent session button; older sessions details list; session open/delete buttons; focus keyword input; chat/planning mode pills; start button. | | `renderWritingEmptyState` | 9185-9253 | Empty state wrapper; SVG icon; title; paragraph; create outline button with inline SVG; hint paragraph. | | `renderFocusKeywordBar` | 9254-9459 | Expanded mode branch; compact mode branch; keyword input behavior; suggestions; selected state; cost/provider indicators; expand/collapse controls. | | `renderAgentWorkspaceCard` | 9460-9629 | Workspace status; collapsed state; context grid; keyword field; conversation/provider summaries; resume card. | | `renderContextIndicator` | 9630-9632 | Alias to `renderAgentWorkspaceCard`, not a new implementation. | | `renderContextualAction` | 9633-9996 | Null guard; `create_outline` action object; clarity check; plan generation stream; contextual action card. | | `renderMessages` | 9997-10917 | Markdown helpers; grouping logic; user messages; AI group; timeline entries; plan cards; edit-plan cards; structured errors; normal response; resume actions. | | `renderConfigTab` | 10918-11434 | Configuration wrapper; article length; language; tone; experience; image/search toggles; SEO section; meta generation; SEO audit result/fix UI; status descriptions. | | `renderGlobalStatusBar` | 11449-11585 | Status dot/label; memory badge; undo; sessions; chat; workspace toggle; config; cost icon buttons. | | `renderChatTab` | 11586-12020 | Lock banners; health notices; welcome/empty/workspace/activity-log gates; command area; hint; textarea; mention/slash autocomplete; search toggle; stop/send buttons; keyboard hints; refine modal. | | `renderCostTab` | 12058-12306 | Cost header; refresh; cost cards; budget section; warning; action summary table; history table; settings footer link. | | Main return | 12307-12346 | `Fragment`; `PluginSidebarMoreMenuItem`; `PluginSidebar`; icon title; `Panel`; `wpaw-tab-content-wrapper`; active tab switch. | ## Nested Function Checklist These nested helpers are easy to lose during component extraction. | Parent | Lines | Nested item | | --- | --- | --- | | `renderClarification` | 8486-8547 | `renderSingleChoice` | | `renderClarification` | 8550-8577 | `renderMultipleChoice` | | `renderClarification` | 8580-8597 | `renderOpenText` | | `renderClarification` | 8600-8723 | `renderConfigForm` | | `renderClarification` | 8725-8742 | `answerInput` switch | | `renderContextualAction` | 9636-9966 | `actions.create_outline` object and async `onClick` | | `renderMessages` | 9998-10006 | `normalizeMessageContent` | | `renderMessages` | 10007-10014 | `escapeHtml` | | `renderMessages` | 10015-10031 | `inlineMarkdownToHtml` | | `renderMessages` | 10032-10270 | `markdownToHtml` | | `markdownToHtml` | 10112-10117 | `flushParagraph` | | `markdownToHtml` | 10118-10140 | `flushList` | | `markdownToHtml` | 10141-10144 | `addListItem` | | `markdownToHtml` | 10145-10156 | `addDetailToLastItem` | | `markdownToHtml` | 10158-10166 | `getListType` | | `renderMessages` | 10271-10276 | `renderMessageContent` | | `renderMessages` | 10278-10312 | group building and user message branch | | `renderMessages` | 10313-10482 | AI group and timeline branch | | `renderMessages` | 10485-10645 | `message.type === "plan"` branch | | `renderMessages` | 10647-10767 | `message.type === "edit_plan"` branch | | `renderMessages` | 10769-10848 | `message.type === "error"` branch | | `renderMessages` | 10850-10909 | default AI response branch | | `renderConfigTab` | 10989-10990 | language list merging | | `renderCostTab` | 12059-12079 | budget percent/status and action summary locals | ## Endpoint Inventory Every endpoint path below is used by `sidebar.js` and must remain present with its existing method, headers, body shape, and response handling. | Lines | Endpoint | | --- | --- | | 379, 411-412 | `/post-config/${postId}` | | 479, 12026-12027 | `/cost-tracking/${postId}` | | 519-520, 558 | `/writing-state/${postId}` | | 1200-1201 | `/seo-audit/${postId}` | | 1468-1469 | `/generate-meta` | | 1813-1814, 1874, 1893-1894, 1931-1932, 1979, 1999-2000, 2122-2123, 2308-2309, 2335-2336, 2413-2414, 2479-2480, 4808-4809, 8836-8837, 8926-8927 | conversation endpoints | | 2143-2144, 2448-2449 | `/conversation/${postId}` and `/conversation/${data.post_id}` | | 2167-2168 | `/chat-history/${postId}` | | 2220 | `/memanto/restore?post_id=${postId}` | | 2612 | `/refine-title` | | 2897-2898, 7354-7355, 7762-7763, 8158-8159, 9809-9810 | `/generate-plan` | | 3288, 6922 | `/chat` | | 3638-3639, 3680 | `/section-blocks/${postId}` and `/section-blocks` | | 3915-3916 | `/summarize-context` | | 3963-3964 | `/detect-intent` | | 4039 | `/clear-context` | | 4103-4104 | `/suggest-keywords` | | 4431-4432 | `/execute-article` | | 4984-4985 | `/reformat-blocks` | | 5087 | `/revise-plan` | | 5969-5970 | `/refine-from-chat` | | 7251-7252, 9681-9682 | `/check-clarity` | ## Editor and Browser Side Effects Preserve these integrations exactly. | Lines | Side effect | | --- | --- | | 300-314 | `localStorage` key `wpaw_agent_workspace_collapsed`. | | 449-473 | Debounced config save via `configSaveTimeoutRef`. | | 683-700, 4769-4794 | `AbortController` lifecycle and active operation state. | | 813-841 | Post saving lock/unlock for writing and refining. | | 842-981 | Editor input lock, block decoration, and global key/paste/drop/cut blockers. | | 1651-1653 | `wp.data.subscribe` workspace snapshot update. | | 1678-1680, 1846-1889, 1970-1994 | `beforeunload` handlers. | | 1692, 1708, 2095 | `localStorage` session keys. | | 1948-1969 | Session lock heartbeat interval. | | 2871-3188, 3258-3473, 4321-4768, 5800-6388, 6759-8056, 8057-8476, 9633-9996 | Stream readers, `TextDecoder`, timeout cleanup, and abort checks. | | 6580-6612 | Window event `wpaw:insert-mention`. | | 9400-9404, 9563-9567 | Focus keyword debounce saves. | | 12349-12356 | `wp.data.withSelect` connection to current post ID. | ## Class Inventory All classes below are present in `sidebar.js`; preserve spelling and combinations. First column is the first line where the class appears. ```text 6075 wpaw-diff-removed 6088 wpaw-diff-added 6129 wpaw-diff-added 6397 wpaw-refine-confirm-overlay 6404 wpaw-refine-confirm-modal 6407 wpaw-refine-confirm-title 6412 wpaw-refine-confirm-body 6428 wpaw-refine-confirm-actions 8493 wpaw-answer-options 8515 wpaw-custom-answer-wrapper 8533 wpaw-custom-text-input 8631 wpaw-config-form 8646 wpaw-config-field 8653 wpaw-config-label 8656 wpaw-config-label-text 8662 wpaw-config-description 8668 wpaw-config-toggle 8682 wpaw-toggle-slider 8706 wpaw-config-text-input 8746 wpaw-clarification-quiz 8746 dark-theme 8749 wpaw-quiz-header 8753 wpaw-progress-bar 8755 wpaw-progress-fill 8770 wpaw-question-card 8775 wpaw-quiz-actions 9011 wpaw-welcome-screen 9014 wpaw-welcome-content 9016 wpaw-welcome-icon 9024 wpaw-welcome-title 9029 wpaw-welcome-subtitle 9037 wpaw-welcome-pill 9065 wpaw-session-list 9086 wpaw-session-open-btn 9135 wpaw-welcome-input 9148 wpaw-welcome-pills 9176 wpaw-welcome-start-btn 9188 wpaw-writing-empty-state 9191 wpaw-empty-state-content 9193 wpaw-empty-state-icon 9210 wpaw-empty-state-button 9244 wpaw-empty-state-hint 9262 wpaw-focus-keyword-bar 9262 wpaw-expanded 9266 wpaw-fk-header 9271 wpaw-fk-collapse 9281 wpaw-fk-main-input 9284 wpaw-fk-custom-input 9311 wpaw-fk-suggestions 9314 wpaw-fk-suggestions-label 9322 wpaw-fk-suggestion-item 9324 selected 9329 wpaw-fk-radio 9334 wpaw-fk-suggestion-text 9339 wpaw-fk-suggestion-source 9348 wpaw-fk-stats 9358 wpaw-provider-info 9370 wpaw-fk-divider 9385 wpaw-compact 9388 wpaw-fk-left 9389 wpaw-fk-icon 9392 wpaw-fk-input 9417 wpaw-fk-cost 9423 wpaw-provider-badge 9435 wpaw-fk-expand 9489 wpaw-agent-workspace-card 9489 is-collapsed 9493 wpaw-agent-workspace-header 9496 wpaw-agent-workspace-heading 9499 wpaw-agent-workspace-kicker 9504 wpaw-agent-workspace-title 9510 wpaw-agent-workspace-actions 9514 wpaw-agent-workspace-status 9514 status-${activeWorkspaceStatus} 9523 wpaw-agent-context-grid 9526 wpaw-agent-context-item 9556 wpaw-agent-keyword-input 9598 wpaw-agent-resume-card 9973 wpaw-contextual-action 9976 wpaw-action-icon 9981 wpaw-action-content 10303 wpaw-message 10303 wpaw-message-user 10307 wpaw-message-content 10343 wpaw-ai-response 10352 complete 10355 inactive 10356 active 10372 wpaw-ai-item 10372 wpaw-timeline-entry 10375 is-current 10378 wpaw-timeline-dot 10383 wpaw-timeline-content 10386 wpaw-timeline-message 10393 wpaw-timeline-complete-row 10402 wpaw-timeline-complete 10407 wpaw-timeline-elapsed 10421 wpaw-inline-undo-btn 10452 wpaw-processing-indicator 10454 wpaw-dots-loader 10469 wpaw-typing-indicator 10475 wpaw-typing-dots 10555 wpaw-plan-card 10559 wpaw-plan-title 10564 wpaw-plan-config-summary 10568 wpaw-config-summary-item 10576 wpaw-plan-sections 10582 wpaw-plan-section 10582 pending 10582 done 10582 in_progress 10586 wpaw-plan-section-row 10588 wpaw-plan-section-check 10596 wpaw-plan-section-body 10599 wpaw-plan-section-title 10607 wpaw-plan-section-desc 10613 wpaw-plan-section-status 10633 wpaw-plan-actions 10676 wpaw-edit-plan 10680 wpaw-edit-plan-title 10685 wpaw-edit-plan-summary 10691 wpaw-edit-plan-preview-label 10697 wpaw-edit-plan-list 10703 wpaw-edit-plan-item 10708 wpaw-edit-plan-item-title 10718 wpaw-edit-plan-item-target 10746 wpaw-edit-plan-actions 10797 wpaw-message-error 10805 wpaw-error-title 10812 wpaw-error-detail 10854 wpaw-response 10858 wpaw-response-content 10884 wpaw-resume-actions 10923 wpaw-tab-content 10923 wpaw-config-tab 10927 wpaw-tab-header 10933 wpaw-config-section 10937 description 10952 wpaw-select 11093 wpaw-config-divider 11161 wpaw-meta-info 11168 good 11169 warning 11192 wpaw-spinning-icon 11210 wpaw-svg-wrapper 11226 wpaw-seo-audit 11229 wpaw-seo-audit-header 11285 wpaw-seo-audit-results 11289 wpaw-seo-score 11295 poor 11299 score-value 11304 score-label 11310 wpaw-seo-stats 11313 wpaw-seo-stat 11316 stat-label 11321 stat-value 11343 wpaw-seo-checks 11352 wpaw-seo-check 11354 passed 11354 failed 11358 check-icon 11363 check-label 11372 wpaw-seo-fix-button 11374 is-fixing 11465 wpaw-status-bar 11471 wpaw-status-indicator 11473 wpaw-status-dot 11477 wpaw-status-label 11486 wpaw-memanto-badge 11495 wpaw-status-actions 11499 wpaw-status-icon-btn 11499 wpaw-undo-btn 11499 has-undo 11512 is-active 11544 wpaw-workspace-toggle-btn 11592 wpaw-chat-tab 11596 wpaw-chat-container 11596 is-dimmed 11603 wpaw-editor-lock-banner 11609 wpaw-refinement-lock-banner 11616 wpaw-session-lock-banner 11627 wpaw-session-lock-takeover 11639 wpaw-health-notice 11670 wpaw-messages 11670 wpaw-activity-log 11674 wpaw-messages-inner 11687 wpaw-command-area 11695 wpaw-input-hint 11695 is-hidden 11707 wpaw-command-input-wrapper 11709 expanded 11713 wpaw-command-prefix 11718 wpaw-input 11758 wpaw-mention-autocomplete 11777 wpaw-mention-option 11877 wpaw-command-actions 11881 wpaw-command-actions-group 11903 wpaw-web-search-toggle 11905 wpaw-search-blocked 11931 wpaw-web-search-icon 11939 wpaw-web-search-label 11953 wpaw-command-circle-btn 11954 wpaw-stop-circle-btn 11955 is-stopping 11964 wpaw-stop-spinner 11972 wpaw-send-circle-btn 11986 wpaw-keyboard-hints 11989 wpaw-kbd 12062 ok 12062 danger 12083 wpaw-cost-tab 12089 wpaw-refresh-btn 12100 wpaw-cost-card 12103 wpaw-cost-stat 12107 wpaw-cost-value 12125 wpaw-cost-remaining 12137 wpaw-budget-section 12140 wpaw-budget-label 12156 wpaw-budget-bar 12158 wpaw-budget-fill 12167 wpaw-budget-warning 12176 wpaw-cost-history 12181 wpaw-cost-table-wrapper 12186 wpaw-cost-table 12285 wpaw-cost-footer 12293 wpaw-cost-settings-link 12338 wpaw-tab-content-wrapper ``` ## Non-Render Class and Selector Inventory These names are not all sidebar `className` props, but they are still source-of-truth migration items. | Lines | Name | Required preservation | | --- | --- | --- | | 824, 828 | `wpaw-writing` | WordPress post-saving lock key. | | 825, 829 | `wpaw-editor-locked` | Body class added/removed while writing lock is active. | | 835, 838 | `wpaw-refining` | WordPress post-saving lock key. | | 836, 839 | `wpaw-refining-locked` | Body class added/removed while refinement lock is active. | | 895, 903, 916 | `wpaw-block-refining` | Editor block DOM class added/removed for refining blocks. | | 933 | `.wpaw-sidebar` | Selector allowlist for editor input blocking. Preserve alongside `.wpaw-command-area` and `.wpaw-messages`. | | 5262 | `wpaw-diff-removed` | Removed from block `className` during diff cleanup. | ## Dynamic Class Expressions These expressions must be migrated as expressions, not flattened. | Lines | Expression behavior | | --- | --- | | 6075-6078, 6111-6114 | Append `wpaw-diff-removed` to editor block `className`. | | 6085-6089, 6128-6129 | Append `wpaw-diff-added` to generated diff blocks. | | 9152-9154 | Welcome chat pill adds `active`. | | 9162-9164 | Welcome planning pill adds `active`. | | 9322-9324 | Focus keyword suggestion item adds `selected`. | | 9489 | Workspace card adds `is-collapsed`. | | 9514 | Workspace status uses `status-${activeWorkspaceStatus}`. | | 10372-10375 | Timeline entry combines `wpaw-ai-item wpaw-timeline-entry`, `statusClass`, and `is-current`. | | 10582 | Plan section uses `section.status || "pending"`. | | 11165-11169 | Meta character count uses `good` or `warning`. | | 11289-11295 | SEO score uses `good`, `warning`, or `poor`. | | 11352-11354 | SEO check uses `passed` or `failed`. | | 11372-11374 | SEO fix button adds `is-fixing`. | | 11473 | Status dot appends `agentStatus`. | | 11510-11512 | Sessions icon button adds `is-active`. | | 11527-11529 | Chat icon button adds `is-active`. | | 11556-11558 | Config icon button adds `is-active`. | | 11570-11572 | Cost icon button adds `is-active`. | | 11596 | Chat container adds `is-dimmed`. | | 11695 | Input hint adds `is-hidden`. | | 11707-11709 | Command input wrapper adds `expanded`. | | 11777-11779 | Mention autocomplete option adds `selected`. | | 11838-11840 | Slash autocomplete option adds `selected`. | | 11903-11905 | Web search toggle adds `wpaw-search-blocked`. | | 11953-11955 | Stop button adds `is-stopping`. | | 12129, 12158, 12167 | Cost/budget UI appends `budgetStatus`. | ## Migration Acceptance Checklist - [ ] `sidebar.js` line ranges 1-12363 are represented in the migrated plan or monolith. - [ ] The component starts from `AgenticWriterSidebar` line 38 and closes at line 12347. - [ ] Final HOC/plugin registration lines 12349-12363 are represented separately. - [ ] Every state/ref/effect in the coverage table exists in the same order. - [ ] Every function in the coverage table exists under the same name. - [ ] Every nested helper in the nested checklist exists. - [ ] Every render surface in the render checklist exists with the same branch gates. - [ ] Every class in the class inventory exists, including dynamic and editor block classes. - [ ] Every endpoint in the endpoint inventory exists with the same request semantics. - [ ] Every editor/browser side effect in the side-effect inventory exists. - [ ] No refactor-only cleanup has been mixed into the first migration pass.