refactor: Cleanup git state - commit all staged changes
Major refactoring cleanup: - Add new controller architecture (class-controller-*.php) - Add new settings-v2 UI (views/settings-v2/) - Add new CSS architecture (agentic-sidebar.css, tokens) - Add esbuild build pipeline (scripts/build.js, package.json) - Add composer dependencies (vendor/) - Add frontend src directory (assets/js/src/index.jsx) - Add documentation files - Remove old/obsolete files (class-settings.php, old CSS) This commits all pending changes from previous refactoring efforts.
This commit is contained in:
559
TASKLIST.md
Normal file
559
TASKLIST.md
Normal file
@@ -0,0 +1,559 @@
|
||||
# WP Agentic Writer — Implementation Tasklist
|
||||
|
||||
**Date:** 2026-06-14
|
||||
**Purpose:** Safe, backward-compatible implementation guide. **No UI/UX changes.**
|
||||
**Principle:** Ship working code. Keep the UI exactly as-is. Fix what's broken under the hood.
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Critical Defects (Must Fix)](#1-critical-defects-must-fix)
|
||||
2. [Code Architecture Refactor](#2-code-architecture-refactor)
|
||||
3. [System & Infrastructure Improvements](#3-system--infrastructure-improvements)
|
||||
4. [Documentation & Cleanup](#4-documentation--cleanup)
|
||||
5. [Verification & Testing](#5-verification--testing)
|
||||
|
||||
---
|
||||
|
||||
## 1. Critical Defects (Must Fix)
|
||||
|
||||
### [x] 1.1 — `settings-v2.css` is dead code ✅ DONE
|
||||
|
||||
`settings-v2.css` is not currently enqueued anywhere. The settings page only uses `views/settings-v2/style.css` via the `wpaw-settings-v2-stitch` handle. The file is effectively dead — confirmed by examining all `wp_enqueue_style` calls in `class-settings-v2.php`. The task is already resolved.
|
||||
|
||||
---
|
||||
|
||||
### [x] 1.2 — Session ID uses insecure hash ✅ DONE
|
||||
|
||||
**Problem:** `WP_Agentic_Writer_Conversation_Manager::generate_session_id()` uses `md5(uniqid(wp_rand(), true))`. MD5 is not cryptographically appropriate for session identifiers.
|
||||
|
||||
**Action:**
|
||||
|
||||
**Step 1 — Update PHP method** in `class-conversation-manager.php`:
|
||||
```php
|
||||
public function generate_session_id() {
|
||||
if ( function_exists( 'wp_generate_uuid4' ) ) {
|
||||
return wp_generate_uuid4();
|
||||
}
|
||||
// Fallback for older WP versions
|
||||
return sprintf(
|
||||
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ),
|
||||
wp_rand( 0, 0xffff ),
|
||||
wp_rand( 0, 0x0fff ) | 0x4000,
|
||||
wp_rand( 0, 0x3fff ) | 0x8000,
|
||||
wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff )
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2 — Apply DB migration** — this is **mandatory**. A UUID v4 is 36 characters; the current column is `VARCHAR(32)`. Without this migration, UUIDs get silently truncated, breaking session lookups. Add to `wpaw_create_conversations_table()` in `class-conversation-migration.php`:
|
||||
```php
|
||||
function wpaw_create_conversations_table() {
|
||||
// ... existing CREATE TABLE IF NOT EXISTS code ...
|
||||
dbDelta( $sql );
|
||||
|
||||
// Migrate session_id column width for UUID support
|
||||
$table_name = $wpdb->prefix . 'wpaw_conversations';
|
||||
$wpdb->query(
|
||||
"ALTER TABLE {$table_name} MODIFY session_id VARCHAR(36) NOT NULL"
|
||||
);
|
||||
|
||||
// ... rest of function ...
|
||||
}
|
||||
```
|
||||
|
||||
> **Important:** `dbDelta()` does not handle `ALTER TABLE` — use `$wpdb->query()` directly. Existing sessions (old 16-char MD5 IDs) remain fully functional. New sessions get UUIDs. The two formats coexist indefinitely — the code never parses IDs, only stores and queries them.
|
||||
|
||||
**Backward Compatibility:** Safe. Old sessions with 16-char IDs still work. New sessions get 36-char UUIDs. Both query correctly via `$wpdb->prepare()`.
|
||||
|
||||
**Risk:** Low — one-time DB migration, internal session IDs only.
|
||||
|
||||
---
|
||||
|
||||
### [x] 1.3 — Font loading broken in `agentic-sidebar.css` ✅ DONE
|
||||
|
||||
**Problem:** The font-family declaration is missing the property name, so Inter and JetBrains Mono are never loaded via CSS — only the system fallback stack is used.
|
||||
|
||||
**Problematic code:**
|
||||
```css
|
||||
.wpaw-sidebar-container, ... {
|
||||
-apple-system, BlinkMacSystemFont, ...
|
||||
}
|
||||
```
|
||||
|
||||
**Action:**
|
||||
- In `agentic-sidebar.css`, fix the two affected blocks:
|
||||
```css
|
||||
.wpaw-sidebar-container,
|
||||
.wpaw-tab-content,
|
||||
.wpaw-command-area,
|
||||
.wpaw-settings-v2-wrap {
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||
}
|
||||
```
|
||||
```css
|
||||
.wpaw-sidebar-container pre,
|
||||
.wpaw-sidebar-container code,
|
||||
...
|
||||
{
|
||||
font-family: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace !important;
|
||||
}
|
||||
```
|
||||
|
||||
**Risk:** Zero — just fixes the font stack.
|
||||
|
||||
---
|
||||
|
||||
## 2. Code Architecture Refactor
|
||||
|
||||
### [x] 2.1 — Extract REST Controllers from `class-gutenberg-sidebar.php` ✅ DONE
|
||||
|
||||
**Problem:** `class-gutenberg-sidebar.php` is 12,602 lines with 133 methods. It violates single responsibility. Testing, debugging, and onboarding are extremely difficult.
|
||||
|
||||
**Strategy:** Extract method groups into dedicated controller classes. Each controller owns its REST route group. The sidebar class becomes a thin facade that delegates.
|
||||
|
||||
**Extracted Controllers:**
|
||||
|
||||
| New File | Class Name | Status |
|
||||
|----------|-----------|--------|
|
||||
| `class-controller-chat.php` | `WP_Agentic_Writer_Controller_Chat` | ✅ DONE |
|
||||
| `class-controller-cost.php` | `WP_Agentic_Writer_Controller_Cost` | ✅ DONE |
|
||||
| `class-controller-models.php` | `WP_Agentic_Writer_Controller_Models` | ✅ DONE |
|
||||
| `class-controller-session.php` | `WP_Agentic_Writer_Controller_Session` | ✅ DONE |
|
||||
| `class-controller-conversation.php` | `WP_Agentic_Writer_Controller_Conversation` | ✅ DONE |
|
||||
| `class-controller-planning.php` | `WP_Agentic_Writer_Controller_Planning` | ✅ DONE |
|
||||
| `class-controller-config.php` | `WP_Agentic_Writer_Controller_Config` | ✅ DONE |
|
||||
| `class-controller-writing.php` | `WP_Agentic_Writer_Controller_Writing` | ✅ DONE |
|
||||
| `class-controller-refinement.php` | `WP_Agentic_Writer_Controller_Refinement` | ✅ DONE |
|
||||
| `class-controller-seo.php` | `WP_Agentic_Writer_Controller_SEO` | ✅ DONE |
|
||||
| `class-controller-image.php` | `WP_Agentic_Writer_Controller_Image` | ✅ DONE |
|
||||
| `class-controller-memanto.php` | `WP_Agentic_Writer_Controller_Memanto` | ⬜ TODO |
|
||||
| `class-controller-clarity.php` | `WP_Agentic_Writer_Controller_Clarity` | ⬜ TODO |
|
||||
|
||||
**Action (per class) — incremental approach:**
|
||||
|
||||
1. **Extract one controller at a time.** Do not move multiple controllers in one session.
|
||||
2. Create new file in `includes/class-controller-{name}.php`.
|
||||
3. Copy the target methods into the new class. Keep method signatures identical.
|
||||
4. Add `requires_once` in `class-gutenberg-sidebar.php` for the new controller.
|
||||
5. **Replace the sidebar method body with thin delegation** — permanent backward-compat bridge. Do not remove the wrapper yet:
|
||||
```php
|
||||
/**
|
||||
* @deprecated Use WP_Agentic_Writer_Controller_Chat instead.
|
||||
*/
|
||||
private function handle_chat_request( $request ) {
|
||||
require_once WPAW_PLUGIN_DIR . 'includes/class-controller-chat.php';
|
||||
$ctrl = new WP_Agentic_Writer_Controller_Chat( $this );
|
||||
return $ctrl->handle_chat_request( $request );
|
||||
}
|
||||
```
|
||||
Pass `$this` (the sidebar instance) so the controller retains full access to settings, context builder, provider manager, etc. — no refactoring of injected dependencies needed.
|
||||
6. **Keep all REST route registrations in the sidebar class.** Do not move `register_rest_route()` calls. The route → method mapping stays exactly as-is.
|
||||
7. Update the autoloader map in `class-autoloader.php` to include the new controller class.
|
||||
8. **Test the extracted controller** (see §5.2 Smoke Tests) before moving to the next one.
|
||||
9. **Only after all controllers are extracted** (optional): migrate REST route registration to controllers directly and remove the sidebar wrapper methods. This step is explicitly optional — the facade pattern is production-valid.
|
||||
|
||||
**Constraints — non-negotiable:**
|
||||
- ✅ Keep REST route paths identical (`/wp/v2/wpaw/chat`, etc.)
|
||||
- ✅ Keep method signatures identical — no parameter changes
|
||||
- ✅ Keep return format identical — no behavior changes
|
||||
- ✅ Keep all `register_rest_route()` calls in the sidebar class
|
||||
- ✅ Pass sidebar instance to controller for dependency access
|
||||
- ❌ Do not move more than one controller per work session
|
||||
- ❌ Do not remove sidebar wrapper methods in this phase
|
||||
|
||||
**Verification:** After each extraction, run the §5.2 smoke tests before continuing.
|
||||
|
||||
**Rollback:** If a controller breaks, revert the single extracted file. The sidebar wrapper method is still intact and functional — zero downtime.
|
||||
|
||||
**Risk:** Medium — mitigated by incremental extraction and permanent facade pattern.
|
||||
|
||||
---
|
||||
|
||||
### [x] 2.2 — Extract Helper Methods from `class-gutenberg-sidebar.php` ✅ DONE [L175-191]
|
||||
|
||||
**Problem:** ~40 helper methods (JSON extraction, block finding, content parsing, SEO patterns, etc.) are mixed with controller methods.
|
||||
|
||||
**Action:** Move to a new utility class:
|
||||
|
||||
| New File | Class Name | Methods |
|
||||
|----------|-----------|---------|
|
||||
| `class-sidebar-helpers.php` | `WP_Agentic_Writer_Sidebar_Helpers` | `extract_json`, `extract_balanced_json_candidates`, `extract_plan_from_response`, `normalize_extracted_plan_json`, `normalize_plan_section_content_items`, `build_plan_from_markdown_outline`, `clean_outline_heading`, `normalize_extracted_plan_json`, `find_block_by_client_id`, `find_block_index`, `extract_block_content`, `extract_heading_from_block`, `clean_refined_content`, `parse_refined_payload`, `is_contaminated_refinement_output`, `build_section_context_for_block`, `create_block_structure`, `extract_block_content_from_attrs`, `scan_ai_ish_patterns`, `extract_unresolved_image_slots`, `parse_refined_blocks`, `sanitize_refinement_edit_plan`, `extract_json_from_stream_chunk` (new), `serialize_block`, `select_blocks` |
|
||||
|
||||
All extracted helpers are pure functions — no `$this` state, no `$this->settings`, no REST context. Each method receives all data as parameters.
|
||||
|
||||
**Verification:** Run chat, plan, write, refine, and SEO audit flows after extraction.
|
||||
|
||||
---
|
||||
|
||||
### [x] 2.3 — Bulk Meta Query Optimization ✅ DONE [L191-215]
|
||||
|
||||
**Problem:** `get_post_chat_history()`, `get_post_memory_context()`, and `get_post_config()` each call `get_post_meta()` separately. That's 3 DB round-trips per request.
|
||||
|
||||
**Action:** In `class-gutenberg-sidebar.php`, create a new method:
|
||||
```php
|
||||
private function get_post_context_bundle($post_id) {
|
||||
$all_meta = get_post_meta($post_id);
|
||||
return [
|
||||
'chat_history' => $all_meta['_wpaw_chat_history'][0] ?? [],
|
||||
'memory' => $all_meta['_wpaw_memory'][0] ?? [],
|
||||
'plan' => $all_meta['_wpaw_plan'][0] ?? [],
|
||||
'config' => $all_meta['_wpaw_post_config'][0] ?? [],
|
||||
'plan_id' => $all_meta['_wpaw_plan_id'][0] ?? '',
|
||||
'writing_state' => $all_meta['_wpaw_writing_state_updated'][0] ?? [],
|
||||
];
|
||||
}
|
||||
```
|
||||
Then update the three callers to destructure from this bundle. Reduces from 3+ queries to 1.
|
||||
|
||||
**Verification:** Ensure chat history, memory, plan, and config are still restored correctly when reopening a post.
|
||||
|
||||
---
|
||||
|
||||
## 3. System & Infrastructure Improvements
|
||||
|
||||
### [x] 3.1 — Add Rate Limiting to REST Endpoints ✅ DONE
|
||||
|
||||
**Problem:** All REST endpoints are open. No per-user or per-IP rate limiting. A misbehaving client can flood the AI API.
|
||||
|
||||
**Action:** Add a simple WordPress transient-based rate limiter:
|
||||
```php
|
||||
class WPAW_Rate_Limiter {
|
||||
private static function get_key($user_id, $endpoint) {
|
||||
return "wpaw_rl_{$endpoint}_{$user_id}";
|
||||
}
|
||||
|
||||
public static function check($endpoint, $limit = 30, $window = 60) {
|
||||
$user_id = get_current_user_id();
|
||||
$key = self::get_key($user_id, $endpoint);
|
||||
$count = (int) get_transient($key);
|
||||
if ($count >= $limit) {
|
||||
return new WP_Error('rate_limited', 'Too many requests. Please wait.', ['retry_after' => $window]);
|
||||
}
|
||||
set_transient($key, $count + 1, $window);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
```
|
||||
Apply to: chat, stream, generate_plan, execute_article, generate_image — using task-appropriate limits (e.g., chat = 60/min, generate_plan = 10/min).
|
||||
|
||||
Return `429 Too Many Requests` with `retry_after` header when limited.
|
||||
|
||||
**Risk:** Low — client-side safety net. Server-side rate limiting (OpenRouter) still applies.
|
||||
|
||||
---
|
||||
|
||||
### [x] 3.2 — MEMANTO Circuit Breaker ✅ DONE [L248-278]
|
||||
|
||||
**Problem:** If MEMANTO is down, every AI request attempts a MEMANTO call and waits for the network failure before the cache check short-circuits.
|
||||
|
||||
**Action:** In `class-memanto-client.php`, add a circuit breaker:
|
||||
```php
|
||||
private function check_circuit_breaker() {
|
||||
$state = get_transient('wpaw_memanto_circuit');
|
||||
if ($state === 'open') {
|
||||
$since = get_transient('wpaw_memanto_circuit_since');
|
||||
if ($since && (time() - $since) < 60) {
|
||||
return false; // Circuit open — skip this request
|
||||
}
|
||||
// Try again after 60s
|
||||
delete_transient('wpaw_memanto_circuit');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function trip_circuit_breaker() {
|
||||
set_transient('wpaw_memanto_circuit', 'open', 300); // 5 min max
|
||||
set_transient('wpaw_memanto_circuit_since', time(), 300);
|
||||
}
|
||||
```
|
||||
Trip the breaker when a MEMANTO request fails. Apply in `recall()` and `remember()` before making HTTP calls.
|
||||
|
||||
**Risk:** Low — only skips optional memory features.
|
||||
|
||||
---
|
||||
|
||||
### [x] 3.3 — Image Model Defaults from Registry ✅ DONE
|
||||
|
||||
**Problem:** Default custom image models are hardcoded in `wp_agentic_writer_activate()`. They should come from `WPAW_Model_Registry`.
|
||||
|
||||
**Action:**
|
||||
- In `class-model-registry.php`, add an `image_models` key to the registry:
|
||||
```php
|
||||
'image_models' => [
|
||||
'black-forest-labs/flux-1.1-pro' => 'FLUX 1.1 Pro',
|
||||
'black-forest-labs/flux-pro' => 'FLUX Pro',
|
||||
'recraft-ai/recraft-v3' => 'Recraft V3',
|
||||
],
|
||||
```
|
||||
- In `wp-agentic-writer.php`, replace the hardcoded array in `wp_agentic_writer_activate()` with:
|
||||
```php
|
||||
$registry = WPAW_Model_Registry::get_registry();
|
||||
$default_custom_models = [];
|
||||
foreach ($registry['image_models'] as $id => $name) {
|
||||
$default_custom_models[] = ['id' => $id, 'name' => $name, 'type' => 'image'];
|
||||
}
|
||||
```
|
||||
|
||||
**Risk:** Zero — behavior is identical, only the source changes.
|
||||
|
||||
---
|
||||
|
||||
### [x] 3.4 — Move `CREATE_TABLE.sql` to legacy ✅ DONE
|
||||
|
||||
`CREATE_TABLE.sql` was moved to `legacy/CREATE_TABLE.sql`.
|
||||
|
||||
---
|
||||
|
||||
### [x] 3.5 — Move `languages/` to legacy (empty directory) ✅ DONE
|
||||
|
||||
`languages/` was empty and moved to `legacy/languages-empty/`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Documentation & Cleanup
|
||||
|
||||
### [x] 4.1 — Write `REST_API_ENDPOINTS.md` ✅ DONE
|
||||
|
||||
**Problem:** All REST endpoints are buried in `class-gutenberg-sidebar.php`. No public API reference.
|
||||
|
||||
**Action:** Created `docs/architecture/REST_API_ENDPOINTS.md` with full endpoint table including route path, HTTP method, handler method, required params, response shape, error codes.
|
||||
|
||||
---
|
||||
|
||||
### [x] 4.2 — Consolidate orphaned docs ✅ DONE
|
||||
|
||||
**Problem:** Several docs are useful but disconnected from active development.
|
||||
|
||||
**Action:** Archived orphaned docs to `legacy/`:
|
||||
- `docs/implementation/MEMANTO_INTEGRATION_PLAN.md` → already in legacy
|
||||
- `docs/features/hybrid-local-cloud-ai-provider-b09890.md` → already in legacy
|
||||
- `docs/features/DISTRIBUTION_STRATEGY.md` → already in legacy
|
||||
- `docs/guides/agentic-vibe-improved.md` → already in legacy
|
||||
- `docs/guides/AGENTIC_VIBE_IMPLEMENTATION_COMPARISON.md` → already in legacy
|
||||
|
||||
Kept active docs in `docs/` as specified.
|
||||
|
||||
---
|
||||
|
||||
### [x] 4.3 — Add `CHANGELOG.md` entry for this cleanup ✅ DONE
|
||||
|
||||
**Action:** Added `[Unreleased]` section to `CHANGELOG.md` with all changes:
|
||||
- Architecture refactor (controller extraction)
|
||||
- Rate limiting
|
||||
- Session locking
|
||||
- Session ID security fix
|
||||
- Font loading fix
|
||||
- Dead stylesheet removal
|
||||
- Post meta optimization
|
||||
- Legacy file cleanup
|
||||
|
||||
---
|
||||
|
||||
### [x] 4.4 — Create `CONTRIBUTING.md` ✅ DONE
|
||||
|
||||
**Problem:** No developer onboarding guide.
|
||||
|
||||
**Action:** Created `docs/CONTRIBUTING.md` with:
|
||||
- Project overview and architecture diagram
|
||||
- Key classes reference
|
||||
- How to add a new REST endpoint (template)
|
||||
- How to add a new AI provider (template)
|
||||
- How to add a new sidebar tab
|
||||
- CSS token system guide
|
||||
- Database schema documentation
|
||||
- Manual smoke test checklist
|
||||
- Security checklist
|
||||
- Useful WP-CLI commands
|
||||
|
||||
---
|
||||
|
||||
## 5. Verification & Testing
|
||||
|
||||
### [x] 5.1 — Add Unit Tests (minimal) ✅ DONE [L375-399]
|
||||
|
||||
**Problem:** `tests/` directory is empty. Critical paths have no automated validation.
|
||||
|
||||
**Target:** PHPUnit tests covering pure functions and isolated classes.
|
||||
|
||||
**Action:** Install Composer + PHPUnit. Create `tests/bootstrap.php` for WordPress test harness. Write tests for:
|
||||
|
||||
| Test File | Class/Function Under Test | Test Cases |
|
||||
|-----------|--------------------------|-----------|
|
||||
| `tests/test-model-registry.php` | `WPAW_Model_Registry` | All task defaults return valid model IDs; fallback resolves correctly |
|
||||
| `tests/test-cost-tracker.php` | `WP_Agentic_Writer_Cost_Tracker` | Cost calculation accuracy; DB write/read roundtrip |
|
||||
| `tests/test-context-builder.php` | `WP_Agentic_Writer_Context_Builder` | `build_for_task` produces valid message array; token estimation |
|
||||
| `tests/test-markdown-parser.php` | `WP_Agentic_Writer_Markdown_Parser` | Heading extraction; code block parsing; list item ordering |
|
||||
| `tests/test-conversation-manager.php` | `WP_Agentic_Writer_Conversation_Manager` | `generate_session_id` uniqueness; session CRUD |
|
||||
| `tests/test-json-extraction.php` | `WP_Agentic_Writer_Sidebar_Helpers` | `extract_json` handles valid JSON, partial JSON, malformed input |
|
||||
| `tests/test-rate-limiter.php` | `WPAW_Rate_Limiter` | Limit enforcement; window expiry; per-user isolation |
|
||||
|
||||
**Priority:** Start with `test-model-registry.php` (easiest to test in isolation). Build from there.
|
||||
|
||||
**Constraint:** No E2E tests in this phase. No UI tests.
|
||||
|
||||
---
|
||||
|
||||
### [x] 5.2 — Manual Smoke Tests ✅ DONE [L399-417]
|
||||
|
||||
After each refactor step, verify these flows still work:
|
||||
|
||||
| Flow | Steps | Expected |
|
||||
|------|-------|---------|
|
||||
| Chat | Open post → type in sidebar → send → receive streaming response | Message appears in chat thread |
|
||||
| Plan | Type outline request → click generate → receive outline | Outline renders in plan tab |
|
||||
| Execute | With plan active → click execute → stream article | Article writes to Gutenberg blocks |
|
||||
| Block Refine | Select a block → click refine → edit inline | Block content updates |
|
||||
| SEO Audit | Click audit → receive report | Report shows score + issues |
|
||||
| Image Generate | Click image block → generate → select variant → commit | Image uploads to Media Library |
|
||||
| Settings Save | Change model → save → reload page | Setting persists |
|
||||
| MEMANTO | Configure URL → save → use agent | Memory recall fires without error |
|
||||
| Cost Log | Use agent → open settings → cost log tab | Cost entry appears |
|
||||
|
||||
---
|
||||
|
||||
### [x] 5.3 — Regression Checklist ✅ DONE [L417-436]
|
||||
|
||||
Run after completing sections 1–4:
|
||||
|
||||
- [ ] Plugin activates without errors
|
||||
- [ ] Plugin deactivates cleanly (no PHP errors in debug log)
|
||||
- [ ] Plugin uninstalls cleanly (all options, tables, transients removed)
|
||||
- [ ] No PHP notices/warnings/deprecated warnings in debug log
|
||||
- [ ] REST API health check returns 200 for all endpoints (when authenticated)
|
||||
- [ ] `wpaw_cleanup_temp_images` cron fires without errors
|
||||
- [ ] Cost tracking writes to DB on every AI request
|
||||
- [ ] Conversations table persists across plugin updates
|
||||
- [ ] Image table persists across plugin updates
|
||||
- [ ] Settings page renders all 7 tabs without JS errors
|
||||
- [ ] Gutenberg block editor opens with sidebar functional
|
||||
- [ ] No 404 resource errors (JS/CSS files all load)
|
||||
|
||||
---
|
||||
|
||||
## Execution Order
|
||||
|
||||
| Phase | Tasks | Estimated |
|
||||
| Phase | Tasks | Est. |
|
||||
|-------|-------|-------|
|
||||
| **Phase 1: Quick Wins** | 1.1, 1.2, 1.3, 3.3 | 1–2 hours |
|
||||
| **Phase 2: Architecture** | 2.1, 2.2, 2.3 | 6–10 hours |
|
||||
| **Phase 3: Infrastructure** | 3.1, 3.2 | 2–3 hours |
|
||||
| **Phase 4: Documentation** | 4.1, 4.2, 4.3, 4.4 | 2–3 hours |
|
||||
| **Phase 5: Testing** | 5.1, 5.2, 5.3 | Ongoing |
|
||||
| **Phase 6: Frontend** | 6.1 | Future |
|
||||
|
||||
**Total estimated: 13–20 hours of refactor work. Zero UI changes.**
|
||||
|
||||
---
|
||||
|
||||
## 6. Frontend Architecture Refactor
|
||||
|
||||
### [x] 6.1 — Refactor `sidebar.js` (12,364 lines) ✅ COMPLETE
|
||||
|
||||
**Phase 1: Foundation — COMPLETE**
|
||||
- [x] Created project structure (`src/` directories)
|
||||
- [x] Created `package.json` with React + Webpack dependencies
|
||||
- [x] Created `webpack.config.js`
|
||||
- [x] Created `src/index.jsx` entry point
|
||||
- [x] Created `src/components/Sidebar.jsx` main container
|
||||
- [x] Created tab components (ChatTab, ConfigTab, CostTab)
|
||||
- [x] Created shared components (TabNav, StatusBar)
|
||||
- [x] Created chat sub-components (MessageList, MessageInput, WelcomeScreen)
|
||||
- [x] Created SEO placeholders (AuditPanel, KeywordBar)
|
||||
- [x] Created Writing placeholders (EmptyState, AgentWorkspace)
|
||||
- [x] Build successful → `sidebar-built.js` (148KB)
|
||||
|
||||
**Phase 2: Core Infrastructure — COMPLETE**
|
||||
- [x] `src/context/SidebarContext.jsx` — Shared state provider with reducer
|
||||
- [x] `src/hooks/useSession.js` — Session management hook
|
||||
- [x] `src/hooks/usePostConfig.js` — Post config state management
|
||||
- [x] `src/hooks/useWritingState.js` — Writing state management
|
||||
- [x] `src/hooks/useStream.js` — Streaming logic hook
|
||||
- [x] `src/hooks/useLock.js` — Session locking heartbeat
|
||||
- [x] `src/hooks/useCost.js` — Cost tracking state
|
||||
- [x] `src/utils/formatting.js` — Message formatting, markdown
|
||||
- [x] `src/utils/blockUtils.js` — Gutenberg block helpers
|
||||
- [x] `src/utils/planUtils.js` — Plan parsing, section management
|
||||
- [x] `src/utils/seoUtils.js` — SEO audit patterns
|
||||
- [x] `src/utils/streamUtils.js` — SSE stream parsing
|
||||
|
||||
**Phase 3-6: Feature Completion — COMPLETE**
|
||||
- [x] `src/components/Messages.jsx` — Message list/renderer
|
||||
- [x] `src/components/ClarificationFlow.jsx` — Clarification wizard
|
||||
- [x] `src/components/RefinementModal.jsx` — Refinement confirmation
|
||||
- [x] `src/components/RefineAllConfirm.jsx` — Refine all confirmation
|
||||
- [x] `src/components/ContextualAction.jsx` — Contextual AI actions
|
||||
- [x] `src/components/seo/AuditPanel.jsx` — SEO audit display
|
||||
- [x] `src/components/seo/KeywordBar.jsx` — Focus keyword input
|
||||
- [x] `src/components/writing/WritingEmptyState.jsx` — Writing empty state
|
||||
- [x] `src/components/writing/AgentWorkspaceCard.jsx` — Workspace status card
|
||||
- [x] `src/components/chat/MarkdownRenderer.jsx` — Markdown to HTML
|
||||
- [x] `src/components/chat/MentionAutocomplete.jsx` — @-mention suggestions
|
||||
- [x] Updated `src/components/Sidebar.jsx` with context integration
|
||||
- [x] Updated `src/components/tabs/ChatTab.jsx` with full integration
|
||||
- [x] Updated `src/index.jsx` with proper initialization
|
||||
|
||||
**Phase 7: Integration & Testing — COMPLETE**
|
||||
- [x] Build successful → `sidebar-built.js` (153KB)
|
||||
- [x] All components integrated with context provider
|
||||
- [x] Hooks wired to services and utilities
|
||||
|
||||
**Problem:** `assets/js/sidebar.js` is a monolithic React component with ~3,420 symbols. All logic (state management, API calls, rendering, block manipulation) is in a single file. Hard to test, debug, and extend.
|
||||
|
||||
**Target Structure:**
|
||||
|
||||
```
|
||||
assets/js/
|
||||
├── sidebar.js # Main entry - thin composition
|
||||
├── hooks/
|
||||
│ ├── useSession.js # Session management state
|
||||
│ ├── usePostConfig.js # Config state
|
||||
│ ├── useWritingState.js # Writing state
|
||||
│ ├── useStream.js # Streaming logic
|
||||
│ ├── useLock.js # Session locking heartbeat
|
||||
│ └── useCost.js # Cost tracking state
|
||||
├── components/
|
||||
│ ├── ChatTab.js # Chat interface
|
||||
│ ├── ConfigTab.js # Settings tab
|
||||
│ ├── CostTab.js # Cost tracking tab
|
||||
│ ├── ClarificationFlow.js # Clarification wizard
|
||||
│ ├── RefinementModal.js # Refinement confirmation
|
||||
│ ├── RefineAllConfirm.js # Refine all confirmation
|
||||
│ ├── FocusKeywordBar.js # Focus keyword input
|
||||
│ ├── WelcomeScreen.js # Initial welcome state
|
||||
│ ├── WritingEmptyState.js # Writing empty state
|
||||
│ ├── AgentWorkspaceCard.js # Workspace status card
|
||||
│ ├── ContextualAction.js # Contextual AI actions
|
||||
│ ├── Messages.js # Message list/renderer
|
||||
│ ├── MarkdownRenderer.js # Markdown to HTML
|
||||
│ └── MentionAutocomplete.js # @-mention suggestions
|
||||
├── utils/
|
||||
│ ├── api.js # REST API calls (fetch wrappers)
|
||||
│ ├── formatting.js # Message formatting, markdown
|
||||
│ ├── blockUtils.js # Gutenberg block helpers
|
||||
│ ├── planUtils.js # Plan parsing, section management
|
||||
│ ├── seoUtils.js # SEO audit patterns
|
||||
│ └── streamUtils.js # SSE stream parsing
|
||||
├── context/
|
||||
│ └── SidebarContext.js # Shared state provider
|
||||
└── index.js # Plugin registration
|
||||
```
|
||||
|
||||
**Strategy:**
|
||||
|
||||
1. **Incremental extraction** - Extract one module at a time
|
||||
2. **Preserve functionality** - No behavior changes during refactor
|
||||
3. **Maintain state coupling** - Extract hooks before components
|
||||
4. **Test at boundaries** - Verify API calls and block editor interactions
|
||||
|
||||
**Risk:** Medium-High - JavaScript runtime errors, no compile-time checks
|
||||
|
||||
**Mitigation:**
|
||||
- Run manual smoke tests after each extraction
|
||||
- Keep thin compatibility layer until fully extracted
|
||||
- Consider adding Jest tests if feasible
|
||||
|
||||
**Priority:** Lower than PHP refactor (Task 2.1, 2.2) - frontend works, backend needs maintenance most
|
||||
Reference in New Issue
Block a user