12 KiB
WP Agentic Writer Twelfth Retrace Audit
Audit date: 2026-05-26
Baseline retraced: docs/architecture/PLUGIN_AUDIT_RETRACE_ELEVENTH_PASS_2026-05-26.md
Scope: twelfth pass after eleventh-retrace implementation, covering chat/context continuity, provider transparency, model registry adoption, cost attribution, UI/UX readiness, and release verification.
Status: COMPLETE / RETRACED
Completion marker: 2026-05-26
Follow-up retrace: docs/architecture/PLUGIN_AUDIT_RETRACE_THIRTEENTH_PASS_2026-05-26.md
This twelfth-pass report has been implemented and retraced. Keep this document as historical evidence only; use the thirteenth-pass report for current remaining work.
Executive Summary
The eleventh-pass implementation closed several meaningful items:
- The sidebar now uses the canonical
/conversation/{post_id}endpoint instead of the deprecated/chat-history/{post_id}endpoint. applyProviderMetadata()is now called from many previously missed frontend paths, including meta generation, summarization, intent detection, reformat blocks, and refine-from-chat completion.- Model registry adoption is broader: Settings V2 fallback labels/defaults, OpenRouter constructor defaults, and image manager defaults now draw from
WPAW_Model_Registry. - PHP and JavaScript syntax checks pass.
No new P0 blocker was found.
The remaining risk is narrower, but one new regression-class issue appeared during retrace: moving the sidebar to /conversation bypasses the legacy chat migration path that still lives under the deprecated chat-history compatibility method. That can make old post-meta chat history disappear from the editor UI for legacy posts that have not yet been migrated into conversation sessions.
Verification Performed
- PHP syntax check across plugin PHP files: passed.
node -c assets/js/sidebar.js: passed.node -c assets/js/settings-v2.js: passed.node -c assets/js/sidebar-utils.js: passed.- Static retrace of eleventh-pass findings against current code.
- Static sweep of provider metadata coverage, model registry usage, chat/context hydration, cost hook contracts, and stale compatibility code.
- No live WordPress editor/browser workflow was run in this pass.
Eleventh-Pass Status Trace
| Eleventh-pass item | Current status | Evidence |
|---|---|---|
Sidebar still used deprecated /chat-history |
Fixed in active sidebar | assets/js/sidebar.js:673 now fetches /conversation/${postId}. |
| Provider metadata missing in meta/summarize/intent/reformat/refine paths | Mostly fixed | applyProviderMetadata() is now called at assets/js/sidebar.js:596, 1603, 1647, 2195, and 2836. |
| Model registry not adopted in Settings V2 fallbacks/OpenRouter/image defaults | Improved | Settings V2 and provider/image defaults now use registry-backed defaults; residual hard-coded presets remain. |
| Raw cost hook drift | Still open | Direct do_action( 'wp_aw_after_api_request', ... ) calls remain, including seven-argument calls that lose provider attribution. |
| Browser verification | Still open | Syntax checks passed, but live editor workflows were not verified. |
Remaining Findings
P1: Canonical /conversation Endpoint Bypasses Legacy Chat Migration
The active sidebar moved to the canonical endpoint:
assets/js/sidebar.js:673fetches/conversation/${postId}.
However, the canonical backend handler only reads an existing conversation session:
includes/class-gutenberg-sidebar.php:1408-1418callsget_session_by_post_id()and returns an empty message list when no session exists.includes/class-conversation-manager.php:200-218returnsnullwhen no active session is found.
The legacy migration behavior still exists, but only in the deprecated compatibility path:
includes/class-gutenberg-sidebar.php:1479-1492reads_wpaw_chat_history, callsmigrate_legacy_chat_history(), and returns migrated messages.
Impact:
- Legacy posts that still have
_wpaw_chat_historybut no conversation session can now hydrate as empty in the sidebar. - This can look like conversation loss after the eleventh-pass fix, even though the data still exists in post meta.
- The deprecated endpoint has the safer migrate-on-read behavior, while the canonical endpoint does not.
Recommended fix:
- Make
handle_get_conversation_by_post()use the same migrate-on-read behavior when no session exists and_wpaw_chat_historyis present. - Return the migrated
session_id,post_id,has_session: true, and messages after migration. - Add a regression test or fixture for a post with only
_wpaw_chat_historyand nowpaw_conversationsrow.
P1: Cost Ledger Still Loses Provider Attribution For Some AI Actions
The centralized track_ai_cost() helper exists, but some AI actions still use the raw hook with the old seven-argument shape.
Examples:
includes/class-keyword-suggester.php:32-34obtains a provider result, butincludes/class-keyword-suggester.php:121-129fireswp_aw_after_api_requestwithout provider, session, or status arguments.includes/class-gutenberg-sidebar.php:6862-6864obtains the provider for improvement analysis, butincludes/class-gutenberg-sidebar.php:6871-6879also fires a seven-argument cost hook.includes/class-cost-tracker.php:50registers the listener with nine accepted arguments, so omitted provider fields fall back tounknown.
Impact:
- Cost rows for keyword suggestions and improvement suggestions can under-report provider and fallback status.
- Provider/cost dashboards can show
unknownfor actions where provider metadata was actually available. - This weakens the new provider transparency work because the UI response and ledger do not always agree.
Recommended fix:
- Replace these raw hook calls with
track_ai_cost()or a shared public cost helper. - Where the helper is not accessible, pass the full nine-argument hook contract, including provider result, session id when available, and status.
- Add a static check for seven-argument
wp_aw_after_api_requestcalls.
P2: Provider Metadata UI Coverage Is Much Better, But Not Exhaustive
The eleventh-pass implementation fixed the major previously listed misses:
- Meta generation calls
applyProviderMetadata(data)atassets/js/sidebar.js:596. - Summarization calls it at
assets/js/sidebar.js:1603. - Intent detection calls it at
assets/js/sidebar.js:1647. - Reformat blocks calls it at
assets/js/sidebar.js:2195. - Refine-from-chat completion calls it at
assets/js/sidebar.js:2836.
Remaining missed or duplicate paths:
- One stream completion branch at
assets/js/sidebar.js:3697-3710emits a completion payload withtotalCostonly, so the frontend has no provider metadata to apply. - Another completion handler at
assets/js/sidebar.js:3930-3945updates cost/timeline without applying provider metadata. - The clarity check path at
assets/js/sidebar.js:4818-4825parsesclarityDatabut does not apply provider metadata from the response.
Impact:
- The provider badge is now reliable for many common flows, but can still remain stale after some generation or clarity workflows.
- Users may see correct cost movement while the provider/fallback display still reflects a previous request.
Recommended fix:
- Ensure every backend AI response and stream completion payload includes
provider_metadatawhen a provider was involved. - Call
applyProviderMetadata(data)immediately after every AI JSON response parse and every streamcompleteevent that can carry metadata. - For endpoints intentionally without provider metadata, document that in code next to the parse/complete branch.
P2: Model Registry Still Has Residual Hard-Coded Defaults And Presets
Registry adoption is now strong in the active PHP defaults, but not complete:
assets/js/settings-v2.js:32-58still defines budget/balanced/premium presets with hard-coded model IDs.includes/class-settings.php:72-78,98-117,138-140,197, and1029-1049still contain legacy settings defaults and presets with hard-coded model IDs.wp-agentic-writer.php:100-104can still instantiate the legacy settings class if Settings V2 is unavailable.
Some hard-coded model strings are acceptable when they are display labels, compatibility checks, pricing keys, or provider-specific suggestions. The remaining concern is default/preset ownership.
Impact:
- The registry is not yet the only source of model defaults users can activate.
- JS presets and legacy settings can drift from the PHP registry.
- Future model migrations still require edits in more than one place.
Recommended fix:
- Localize presets from
WPAW_Model_Registry::get_frontend_data()or add explicit registry preset support. - Either retire the legacy
WP_Agentic_Writer_Settingspath or make it read registry defaults. - Keep provider suggestion maps and pricing tables separate, but name them as suggestions/pricing rather than defaults.
P2: Live Browser Verification Is Still The Final Release Gate
Static checks passed, but the plugin still needs a live editor pass before calling the audit chain fully complete.
Manual verification should cover:
- Sidebar opens in the block editor and survives page reload.
- Existing legacy post-meta chat history migrates and appears through
/conversation/{post_id}. - New chat messages persist, reload, and retain session id continuity.
- Provider/fallback badges update after chat, clarity, planning, generation, refinement, summarize, reformat, meta, keyword, and improvement actions.
- Cost totals update in the UI and cost ledger with provider/session/status fields populated.
- Model setting changes affect generated requests and visible provider metadata.
- Unauthorized REST access remains denied.
P3: Stale Compatibility Comments And Backup Files Can Create Audit Noise
The deprecated chat-history docblock is now stale:
includes/class-gutenberg-sidebar.php:1349-1350says the endpoint does not use the conversations table, but the implementation delegates through conversation/session migration behavior.
Also, backup JavaScript files still reference old endpoint behavior:
assets/js/sidebar.js.backupassets/js/sidebar.js.bak
Impact:
- Future retraces can mistake backup files or stale comments for active behavior.
- If backup files are accidentally packaged, old endpoint usage can leak into distribution artifacts.
Recommended fix:
- Update the deprecated endpoint docblock to describe the actual compatibility behavior.
- Exclude backup files from packaging or remove them after confirming they are not needed.
Priority Queue
- P1: Add migrate-on-read behavior to
/conversation/{post_id}for legacy_wpaw_chat_history. - P1: Fix seven-argument cost hooks for keyword and improvement suggestions so provider attribution is preserved.
- P2: Finish provider metadata propagation for remaining stream completion and clarity branches.
- P2: Move active JS presets and legacy settings defaults under the model registry, or explicitly retire/de-scope legacy settings.
- P2: Run live WordPress editor browser verification.
- P3: Clean stale chat-history comments and backup endpoint references.
Completion Criteria For Next Pass
The next retrace can mark this pass complete when:
/conversation/{post_id}migrates legacy chat history when no session exists.- Keyword and improvement suggestion cost rows include provider, fallback, session/status where available.
- Provider metadata is applied or explicitly de-scoped for every AI response path.
- Remaining model preset/default ownership is either centralized in the registry or documented as intentional.
- A live editor verification note exists with the exact workflows checked.