feat: consolidate docs, backend/session infra, and settings updates
This commit is contained in:
276
docs/architecture/PLUGIN_AUDIT_RETRACE_2026-05-24.md
Normal file
276
docs/architecture/PLUGIN_AUDIT_RETRACE_2026-05-24.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# WP Agentic Writer Retrace Audit
|
||||
|
||||
Status: COMPLETE / SUPERSEDED
|
||||
Completion marker date: 2026-05-24
|
||||
Next retrace report: `docs/architecture/PLUGIN_AUDIT_RETRACE_SECOND_PASS_2026-05-24.md`
|
||||
|
||||
Audit date: 2026-05-24
|
||||
Baseline retraced: `docs/architecture/PLUGIN_AUDIT_FOLLOWUP_2026-05-24.md`
|
||||
Scope: current implementation after follow-up fixes, with emphasis on UI/UX, system boundaries, conversation context/history, cost tracker, provider/model routing, migrations, and data lifecycle.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The follow-up implementation closed several important items, but the plugin is not yet clean enough to shift only into chat/context implementation. The highest-risk remaining problem is a new provider contract mismatch: `WP_Agentic_Writer_Provider_Manager::get_provider_for_task()` now returns a `WPAW_Provider_Selection_Result`, but several older classes still treat the return value as a provider and call `->chat()` or `->generate_image()` directly. That can fatal in image, keyword, and WP AI wrapper paths.
|
||||
|
||||
The second urgent issue is streaming chat state: `stream_chat_request()` currently references `$accumulated_content`, `$chunks_emitted`, and `$last_user_message` without initializing them. That can corrupt streaming persistence and produce warnings or missing session messages.
|
||||
|
||||
Good news: OpenRouter cache separation is now implemented, several conversation permissions were tightened, settings cost-log pagination was improved, and chat responses now include provider metadata. But there are still cross-cutting runtime, migration, cost-ledger, and authorization gaps.
|
||||
|
||||
## Verification Performed
|
||||
|
||||
- PHP syntax check across plugin PHP files: passed.
|
||||
- JS syntax check: `node -c assets/js/sidebar.js` and `node -c assets/js/settings-v2.js` passed.
|
||||
- Static trace of follow-up audit items against current code.
|
||||
- No live WordPress browser workflow was run in this pass.
|
||||
|
||||
## Follow-up Status Trace
|
||||
|
||||
| Follow-up item | Current status | Evidence |
|
||||
|---|---:|---|
|
||||
| Split OpenRouter model cache keys | Fixed | Full objects use `wpaw_openrouter_model_objects`; IDs use `wpaw_openrouter_model_ids` in `includes/class-openrouter-provider.php:106-264`. |
|
||||
| Add post/session auth for conversation list/create/link | Mostly fixed | `edit_post` added for post-linked conversation routes and link-post checks session access in `includes/class-gutenberg-sidebar.php:7263-7555`. |
|
||||
| Add writing-state post auth | Fixed | `edit_post` checks and status allowlist added in `includes/class-gutenberg-sidebar.php:823-887`. |
|
||||
| Provider fallback metadata for chat | Partially fixed | Provider result object and chat response metadata exist in `includes/class-provider-manager.php:20-92` and `includes/class-gutenberg-sidebar.php:987-1029`, but helper classes still use the old API. |
|
||||
| Cost log SQL pagination | Improved | Grouping/pagination moved into SQL in `includes/class-settings-v2.php:645-667`. |
|
||||
| Conversation table migration versioning | Still open | Migration still checks `wpaw_db_version`, not `wpaw_conversations_db_version`, in `includes/class-conversation-migration.php:67-72`. |
|
||||
| Single source of truth for chat messages | Partially fixed | Chat no longer writes new `_wpaw_chat_history`, but legacy methods/routes remain and migration does not delete migrated meta. |
|
||||
| Cost tracker provider/session/status ledger | Partially fixed | New columns and parameters exist, but hook accepts only 7 args in `includes/class-cost-tracker.php:48-53`, so session/status are dropped. |
|
||||
| Model registry/default unification | Still open | Defaults remain fragmented across activation, providers, settings PHP, JS, and WP AI wrapper. |
|
||||
| Uninstall/data lifecycle | Still open | Main uninstall and `uninstall.php` remain inconsistent and incomplete. |
|
||||
| Debug logging | Still open | Backend and frontend debug logs remain broad. |
|
||||
|
||||
## Critical Findings
|
||||
|
||||
### P0: Provider Manager Return Contract Breaks Older Callers
|
||||
|
||||
`get_provider_for_task()` now returns `WPAW_Provider_Selection_Result`, which is correct for provider transparency. But not every caller was updated to use `$provider_result->provider`.
|
||||
|
||||
Broken paths:
|
||||
- Image placement analysis calls `$provider->chat()` on the selection result in `includes/class-image-manager.php:218-219`.
|
||||
- Image prompt generation does the same in `includes/class-image-manager.php:295-296`.
|
||||
- Image variant generation calls `$provider->generate_image()` on the selection result in `includes/class-image-manager.php:478-483`.
|
||||
- Keyword suggester calls `$provider->chat()` on the selection result in `includes/class-keyword-suggester.php:32-84`.
|
||||
- WP AI legacy wrapper calls `$provider->chat()`, `$provider->chat_stream()`, and `$provider->get_name()` on the selection result in `includes/class-wp-ai-client-wrapper.php:225-252` and `includes/class-wp-ai-client-wrapper.php:272-280`.
|
||||
|
||||
Impact:
|
||||
- Image generation, image prompt analysis, keyword suggestions, and WP AI fallback paths can fatal with "Call to undefined method WPAW_Provider_Selection_Result::chat()".
|
||||
- This is a classic fix-A-break-B regression from changing a shared service contract.
|
||||
|
||||
Recommended fix:
|
||||
- Update all callers to:
|
||||
- `$provider_result = WP_Agentic_Writer_Provider_Manager::get_provider_for_task( ... );`
|
||||
- `$provider = $provider_result->provider;`
|
||||
- propagate `$provider_result->actual_provider`, `fallback_used`, and `warnings` where returned or tracked.
|
||||
- Consider adding `__call()` only as a temporary compatibility shim if too many callers exist, but explicit updates are safer.
|
||||
|
||||
### P0: Streaming Chat Uses Uninitialized State
|
||||
|
||||
`stream_chat_request()` references variables that are never initialized in the current implementation.
|
||||
|
||||
Evidence:
|
||||
- Closure captures `$accumulated_content` and `$chunks_emitted` by reference in `includes/class-gutenberg-sidebar.php:1089-1109`.
|
||||
- `$chunks_emitted` is compared at `includes/class-gutenberg-sidebar.php:1111-1121`.
|
||||
- `$accumulated_content` is used at `includes/class-gutenberg-sidebar.php:1158-1164`.
|
||||
- `$last_user_message` is stored into session messages at `includes/class-gutenberg-sidebar.php:1169-1177`, but is never assigned inside the method.
|
||||
|
||||
Impact:
|
||||
- Streaming chat can emit warnings/notices and fail to persist the user message correctly.
|
||||
- Session history may save an empty or undefined user message while the assistant message is stored.
|
||||
- This directly affects the chat/context path the team wants to focus on.
|
||||
|
||||
Recommended fix:
|
||||
- Restore initializers at the top of `stream_chat_request()`:
|
||||
- `$accumulated_content = '';`
|
||||
- `$chunks_emitted = 0;`
|
||||
- `$last_user_message = $this->get_last_user_message( $messages );`
|
||||
- `$total_cost = 0;`
|
||||
|
||||
### P0: Image Generation Is Broken By Provider Contract Mismatch
|
||||
|
||||
Image generation was already a sensitive flow because it touches model routing, temporary files, cost, and DB state. The provider result contract now breaks it before generation.
|
||||
|
||||
Evidence:
|
||||
- `generate_image_variants()` assigns provider result to `$provider` at `includes/class-image-manager.php:478`.
|
||||
- It calls `$provider->generate_image()` at `includes/class-image-manager.php:483`.
|
||||
|
||||
Impact:
|
||||
- `/generate-image` can fail at runtime even though PHP syntax passes.
|
||||
- Image generation costs still will not reliably reach the main cost ledger because generation is interrupted before any ledger call.
|
||||
|
||||
Recommended fix:
|
||||
- Unwrap provider result and track image generation through `wp_aw_after_api_request` with provider/session/status metadata.
|
||||
|
||||
## High Priority Findings
|
||||
|
||||
### P1: Cost Tracker Hook Drops Session and Status Metadata
|
||||
|
||||
The Cost Tracker now accepts provider, session ID, and status, but the hook registration only allows 7 arguments.
|
||||
|
||||
Evidence:
|
||||
- Hook registration accepts 7 args in `includes/class-cost-tracker.php:48-53`.
|
||||
- `add_request()` signature expects 9 args in `includes/class-cost-tracker.php:113-133`.
|
||||
- Chat emits provider, session ID, and status in `includes/class-gutenberg-sidebar.php:1011-1023` and `includes/class-gutenberg-sidebar.php:1144-1156`.
|
||||
|
||||
Impact:
|
||||
- Provider may be recorded, but `session_id` and explicit `status` are silently dropped.
|
||||
- Failed calls still are not intentionally recorded.
|
||||
- Cost records cannot be reconciled to conversation context.
|
||||
|
||||
Recommended fix:
|
||||
- Change hook registration to `add_action( 'wp_aw_after_api_request', array( $this, 'add_request' ), 10, 9 );`.
|
||||
- Add explicit failure ledger entries around provider errors.
|
||||
- Add `error_code`/`request_id` if this is meant to be a true ledger.
|
||||
|
||||
### P1: Conversation Migration Is Still Version-fragile
|
||||
|
||||
The follow-up audit recommended conversation-specific migration versioning, but the migration runner still checks the main DB version.
|
||||
|
||||
Evidence:
|
||||
- Conversation table creation stores `wpaw_conversations_db_version` in `includes/class-conversation-migration.php:43-47`.
|
||||
- `wpaw_run_migrations()` still reads `wpaw_db_version` in `includes/class-conversation-migration.php:67-72`.
|
||||
- Main table creation remains gated by `wpaw_db_version < 1.1.0` in `wp-agentic-writer.php:223-241`.
|
||||
- Conversation cleanup cron is scheduled at include time in `includes/class-conversation-migration.php:94-99`.
|
||||
|
||||
Impact:
|
||||
- Existing installs with `wpaw_db_version=1.1.0` but no conversation table can still be skipped.
|
||||
- Cleanup cron can run against a missing table.
|
||||
|
||||
Recommended fix:
|
||||
- Run an idempotent `wpaw_ensure_conversations_table()` based on `wpaw_conversations_db_version` or direct table existence.
|
||||
- Unschedule `wpaw_cleanup_old_sessions` on deactivation.
|
||||
|
||||
### P1: Chat History Is Better, But Legacy Read/Migration Still Keeps Two Truths Alive
|
||||
|
||||
New chat writes no longer call `update_post_chat_history()`, which is good. But legacy post-meta read/write helpers and migration behavior still keep `_wpaw_chat_history` alive.
|
||||
|
||||
Evidence:
|
||||
- New chat comments say legacy meta is deprecated in `includes/class-gutenberg-sidebar.php:1031-1053` and `includes/class-gutenberg-sidebar.php:1167-1187`.
|
||||
- `/chat-history/{post_id}` still reads legacy meta in `includes/class-gutenberg-sidebar.php:1240-1256`.
|
||||
- Legacy update helper still exists and writes meta in `includes/class-gutenberg-sidebar.php:1268-1301`.
|
||||
- Context Service `get_context()` does not migrate on read in `includes/class-context-service.php:62-87`.
|
||||
- Migration still leaves legacy meta in place in `includes/class-context-service.php:299-300`.
|
||||
|
||||
Impact:
|
||||
- Legacy history can still be surfaced, migrated more than once, or diverge from the session table.
|
||||
- Clear context does not clear an active session unless another caller invokes `Context_Service::clear_context()` with a session ID.
|
||||
|
||||
Recommended fix:
|
||||
- Make `/chat-history/{post_id}` migration-only or remove it after frontend no longer needs it.
|
||||
- Delete or mark `_wpaw_chat_history` after successful migration.
|
||||
- Call migration from `Context_Service::get_context()` when legacy meta exists.
|
||||
- Update `handle_clear_context()` to require `edit_post` and clear active session messages when `sessionId` is present.
|
||||
|
||||
### P1: Post-scoped Authorization Remains Incomplete Outside Conversation Routes
|
||||
|
||||
Conversation routes improved, but other post-scoped routes still trust the broad `edit_posts` permission callback.
|
||||
|
||||
Examples:
|
||||
- Post config get/update read and write `_wpaw_post_config` without `edit_post` in `includes/class-gutenberg-sidebar.php:1722-1756`.
|
||||
- Cost tracking for a post lacks a target post check in `includes/class-gutenberg-sidebar.php:3623-3629`.
|
||||
- Section block mapping reads/writes post meta without `edit_post` in `includes/class-gutenberg-sidebar.php:4776-4835`.
|
||||
- Image recommendation/generate/commit routes are registered with broad permissions at `includes/class-gutenberg-sidebar.php:593-620` and handlers lack target post checks in `includes/class-gutenberg-sidebar.php:6457-6520`.
|
||||
|
||||
Impact:
|
||||
- Multi-author sites can still leak or mutate post-scoped state across users.
|
||||
- This is larger than conversations and should be fixed as a shared helper.
|
||||
|
||||
Recommended fix:
|
||||
- Add a helper like `require_edit_post_or_error( $post_id, $action )`.
|
||||
- Apply it to every route that reads or writes post meta, cost, image state, SEO/GEO state, or generated content.
|
||||
|
||||
## Medium Priority Findings
|
||||
|
||||
### P2: Provider Metadata Is Not Yet Consistent Across All AI Responses
|
||||
|
||||
Chat responses now include provider metadata, but planning/writing/refinement/clarity helper responses often only track cost internally and do not return provider/warning metadata to the frontend.
|
||||
|
||||
Evidence:
|
||||
- Chat adds metadata in `includes/class-gutenberg-sidebar.php:1025-1029` and streaming complete event includes metadata in `includes/class-gutenberg-sidebar.php:1190-1199`.
|
||||
- Many other calls use `$provider_result` internally but return older response shapes.
|
||||
|
||||
Opportunity:
|
||||
- Standardize an AI response envelope for all REST/SSE flows: `content`, `provider`, `selected_provider`, `model`, `fallback_used`, `warnings`, `cost`, `usage`, `request_id`.
|
||||
|
||||
### P2: Model Defaults Are Still Fragmented
|
||||
|
||||
No single model registry exists yet. Defaults remain spread across activation, OpenRouter provider, settings V2, legacy settings, JS presets, Image Manager, and WP AI wrapper.
|
||||
|
||||
Evidence:
|
||||
- Activation still stores `execution_model` in `wp-agentic-writer.php:140-142`.
|
||||
- OpenRouter defaults differ across properties in `includes/class-openrouter-provider.php:34-69`.
|
||||
- Settings V2 still has multiple fallback groups in `includes/class-settings-v2.php:105-111`, `includes/class-settings-v2.php:228-273`, and `includes/class-settings-v2.php:989-994`.
|
||||
- JS presets remain in `assets/js/settings-v2.js:24-38`.
|
||||
- Image Manager has its own writing/image fallbacks in `includes/class-image-manager.php:183-248`.
|
||||
|
||||
Recommendation:
|
||||
- Add a PHP `Model_Registry` and localize it to settings JS.
|
||||
- Stop writing `execution_model` for fresh installs.
|
||||
|
||||
### P2: Cost Table Schema Is Split Between Creation and Runtime ALTER
|
||||
|
||||
The runtime upgrader adds columns, but the base table creation in the main plugin file still creates the old schema.
|
||||
|
||||
Evidence:
|
||||
- Base schema lacks provider/session/status in `wp-agentic-writer.php:198-209`.
|
||||
- Runtime `ALTER TABLE` adds provider/session/status in `includes/class-cost-tracker.php:61-97`.
|
||||
|
||||
Risk:
|
||||
- Fresh installs depend on Cost Tracker initialization to complete schema.
|
||||
- Failed `DESCRIBE` on a missing table is not handled before `in_array()` checks.
|
||||
|
||||
Recommendation:
|
||||
- Move the latest schema into `wp_agentic_writer_create_cost_table()`.
|
||||
- Make runtime migrations table-existence safe and versioned.
|
||||
|
||||
### P2: Uninstall Is Still Incomplete And Duplicated
|
||||
|
||||
The main uninstall hook and `uninstall.php` remain inconsistent.
|
||||
|
||||
Evidence:
|
||||
- Main uninstall deletes settings and some tables in `wp-agentic-writer.php:269-294`.
|
||||
- `uninstall.php` deletes settings, `_wpaw_plan`, and cost table only in `uninstall.php:12-21`.
|
||||
|
||||
Still missing:
|
||||
- `wpaw_conversations`, `wp_agentic_writer_custom_models`, DB version options, transients, scheduled `wpaw_cleanup_old_sessions`, `_wpaw_chat_history`, `_wpaw_memory`, `_wpaw_post_config`, writing-state meta, user preferences, and image post meta.
|
||||
|
||||
### P2: Debug Logging Remains Too Broad
|
||||
|
||||
There is a localized `debug` flag, but console logs and backend logs remain noisy.
|
||||
|
||||
Evidence:
|
||||
- `wpAgenticWriter.debug` is localized in `includes/class-gutenberg-sidebar.php:257`.
|
||||
- Frontend still logs migration/session/clarity details in `assets/js/sidebar.js:308-322`, `assets/js/sidebar.js:5619-5630`, and `assets/js/sidebar.js:6130-6157`.
|
||||
- Settings JS logs model and cost debug info in `assets/js/settings-v2.js:52-130` and `assets/js/settings-v2.js:390-503`.
|
||||
- Provider/backend `error_log()` calls remain in provider files and `class-gutenberg-sidebar.php`.
|
||||
|
||||
### P2: Changelog Policy Still Fails
|
||||
|
||||
`docs/DEFINITION_OF_DONE.md` requires updating `CHANGELOG.md`, but no `CHANGELOG.md` file was found.
|
||||
|
||||
## Recommended Next Work Queue
|
||||
|
||||
### Do Before Chat/Context Focus
|
||||
|
||||
1. Fix provider result contract callers in Image Manager, Keyword Suggester, and WP AI Client wrapper.
|
||||
2. Restore streaming chat variable initialization.
|
||||
3. Change Cost Tracker hook accepted args from 7 to 9 and add failure recording.
|
||||
4. Fix conversation migration versioning and cleanup cron scheduling.
|
||||
|
||||
### Then Focus Chat/Context
|
||||
|
||||
1. Make `Context_Service::get_context()` migrate legacy history on read.
|
||||
2. Delete or mark migrated `_wpaw_chat_history`.
|
||||
3. Make clear-context clear both post context and active session messages.
|
||||
4. Add a visible context inspector in the UI: active session, message count, linked post, focus keyword, language, provider/model, cost estimate.
|
||||
|
||||
### Later
|
||||
|
||||
1. Apply `edit_post` checks to every post-scoped route.
|
||||
2. Centralize model defaults in a registry.
|
||||
3. Consolidate uninstall/data retention.
|
||||
4. Gate logging.
|
||||
5. Add `CHANGELOG.md`.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Do not switch solely to chat/context yet. The implementation is closer, but the provider contract mismatch and streaming-chat uninitialized state should be fixed first because they directly break runtime behavior and chat persistence. After those are resolved, chat/context is the right next focus.
|
||||
Reference in New Issue
Block a user