10 KiB
WP Agentic Writer Tenth Retrace Audit
Status: COMPLETE / RETRACED
Completion marker: 2026-05-26
Follow-up report: docs/architecture/PLUGIN_AUDIT_RETRACE_ELEVENTH_PASS_2026-05-26.md
Audit date: 2026-05-26
Baseline retraced: docs/architecture/PLUGIN_AUDIT_RETRACE_NINTH_PASS_2026-05-26.md
Scope: tenth pass after ninth-retrace implementation, covering failed-attempt tracking, provider transparency, model registry adoption, chat/context compatibility, cost tracking contracts, UI/UX, and release readiness.
Executive Summary
The ninth-pass implementation fixed the P0 runtime blocker:
- The failed-attempt branches no longer call
$provider_result->get_default_model(). - They now use
WPAW_Model_Registry::get_default_model()for writing, clarity, and refinement paths. - PHP and JavaScript syntax checks pass.
The implementation also improved two other areas:
- Provider metadata now reaches the sidebar in the streaming completion path and is rendered as a compact provider/fallback badge near cost.
- Model registry adoption improved across active settings paths, sidebar defaults, activation defaults, image-manager analysis/prompt paths, and failed-attempt model fallbacks.
No new P0 blocker was found in this retrace. The remaining gaps are now mostly completion and verification work:
- Provider metadata UI is only wired for the streaming completion path, not every non-streaming AI response path.
- The model registry exists and is partially adopted, but some model defaults/fallbacks are still hard-coded.
- The sidebar still hydrates chat from the deprecated
/chat-historycompatibility route. - Raw cost hook calls still exist outside
track_ai_cost(). - Live WordPress editor browser verification is still pending.
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 ninth-pass findings against current code.
- Static sweep of failed-attempt tracking, provider metadata UI usage, model registry adoption, chat-history usage, and raw cost hooks.
- No live WordPress editor/browser workflow was run in this pass.
Ninth-Pass Status Trace
| Ninth-pass item | Current status | Evidence |
|---|---|---|
P0 failed-attempt fatal from $provider_result->get_default_model() |
Fixed | Failed branches now call WPAW_Model_Registry::get_default_model() at includes/class-gutenberg-sidebar.php:3796-3805, 4163-4172, 7004-7012, and 7102-7110. |
| Failed-attempt cost helper | Improved | track_ai_cost() exists at includes/class-gutenberg-sidebar.php:966-1005 and is used in sampled failure branches. |
| Provider metadata backend envelope | Improved | Chat adds provider_metadata at includes/class-gutenberg-sidebar.php:1114, while many backend responses already include the same envelope. |
| Provider metadata editor rendering | Partially fixed | Sidebar captures provider metadata from streaming complete events at assets/js/sidebar.js:1023-1031 and renders a provider/fallback badge at assets/js/sidebar.js:4658-4665 and assets/js/sidebar.js:4701-4708. |
| Model registry adoption | Improved but incomplete | Active settings defaults use WPAW_Model_Registry in includes/class-settings-v2.php:100-111, 989-994, and 1109-1114; hard-coded defaults remain elsewhere. |
Sidebar dependency on /chat-history |
Still open | assets/js/sidebar.js:644-668 still fetches /chat-history/${postId}. |
| Raw cost hook drift | Still open | Many direct do_action( 'wp_aw_after_api_request', ... ) calls remain in includes/class-gutenberg-sidebar.php. |
| WordPress editor browser pass | Still open | Syntax checks passed, but no live editor workflow was verified. |
Remaining Findings
P1: Provider Metadata UI Is Only Partially Wired
The sidebar now has provider metadata state and renders it:
providerInfostate exists atassets/js/sidebar.js:73.- Streaming completion events capture
data.providerordata.provider_metadataatassets/js/sidebar.js:1023-1031. - A provider/fallback badge renders near cost in the focus keyword UI at
assets/js/sidebar.js:4658-4665andassets/js/sidebar.js:4701-4708.
The gap is coverage. The only setProviderInfo() call found is in the streaming completion handler. Many non-streaming fetch flows parse JSON responses that may include provider_metadata, but they do not appear to update providerInfo:
- Plan generation/revision non-stream paths.
- Chat non-stream responses if enabled.
- Meta generation.
- Summarize context and intent detection.
- Refine/reformat utility calls.
Impact:
- Provider transparency is visible only for some workflows.
- Users can still run AI actions with provider metadata in the response but no visible provider/fallback update in the sidebar.
- The Definition of Done expects actual provider visibility across AI actions, not only one streaming flow.
Recommended fix:
- Add one frontend helper, for example
applyProviderMetadata(responseData), and call it after every AI JSON response and stream completion. - Support both
provider_metadataand top-level provider fields while backend response shapes continue to coexist. - Add a small UI checklist or browser assertion that provider info updates after chat, plan, refine, meta, and utility actions.
P1: Model Registry Adoption Is Improved But Still Not A Single Source Of Truth
The registry is now more than a stub:
WPAW_Model_Registryexists inincludes/class-model-registry.php.- Activation uses registry defaults at
wp-agentic-writer.php:140-145. - Active settings V2 localization and sanitization use registry defaults at
includes/class-settings-v2.php:100-111andincludes/class-settings-v2.php:989-994. - Sidebar defaults use registry defaults at
includes/class-gutenberg-sidebar.php:278-283. - Image-manager analysis/prompt paths now use registry defaults at
includes/class-image-manager.php:183-249.
But several hard-coded model defaults or model lists remain:
includes/class-settings-v2.php:188-215still has fallback model arrays with literal model ids.includes/class-settings-v2.php:224-230still uses literal fallback ids in model transformation.assets/js/settings-v2.js:32-58still hard-codes budget/balanced/premium preset ids.includes/class-openrouter-provider.php:29-75still hard-codes provider property defaults, even though comments say they are registry-sourced.includes/class-image-manager.php:409-478still hard-codes image-model fallback values.- Legacy
includes/class-settings.phpstill contains old hard-coded defaults, andwp-agentic-writer.php:101-104can still instantiate it if Settings V2 is unavailable.
Impact:
- Runtime defaults can still drift from registry defaults.
- Fallback UI/model lists can disagree with actual generation defaults.
- The registry is useful now, but it is not yet enforcing the "single source of truth" claim.
Recommended fix:
- Replace remaining fallback literals in active runtime paths with
WPAW_Model_Registry::get_default_model()orget_fallback_model(). - Decide whether JS presets are curated product presets or registry-derived defaults. If curated, document them outside the "single source of truth" claim.
- Initialize OpenRouter default properties from the registry in the constructor, or remove property defaults as authoritative values.
- Either update legacy
class-settings.phpor clearly mark it as inactive/deprecated and remove fallback instantiation. - Add a static check that flags task-default strings outside the registry, except approved curated presets and pricing maps.
P2: Sidebar Still Depends On Deprecated /chat-history
The earlier data-loss bug is fixed, but the frontend still hydrates chat through a deprecated compatibility endpoint:
assets/js/sidebar.js:644-668calls/chat-history/${postId}.- The backend compatibility route remains registered at
includes/class-gutenberg-sidebar.php:346-354.
Impact:
- The UI still depends on a route whose name and docblock communicate legacy post-meta history.
- Future cleanup could accidentally break chat hydration.
- It keeps one old mental model alive even though conversations are now session-backed.
Recommended fix:
- Move sidebar hydration to the canonical conversation/session context endpoint.
- If
/chat-historyremains, update its docblock and response contract to make clear that it returns session-backed compatibility data.
P2: Raw Cost Hook Calls Still Bypass The New Helper
The new track_ai_cost() helper is a good step, but direct do_action( 'wp_aw_after_api_request', ... ) calls remain throughout includes/class-gutenberg-sidebar.php.
Impact:
- New work can still reintroduce incomplete provider/session/status tracking.
- Cost tracking consistency still depends on manual discipline.
Recommended fix:
- Convert direct cost hook calls in
class-gutenberg-sidebar.phptotrack_ai_cost(). - Add a static guard that only allows raw
wp_aw_after_api_requestintrack_ai_cost()and the cost tracker registration.
P2: Live Editor Browser Verification Still Remains
The screenshot correctly identifies browser verification as the remaining manual task. Static checks cannot prove the editor workflow works.
Recommended browser checklist:
- Sidebar opens and persists in the block editor.
- Chat session continues after page reload.
- Provider/fallback warnings render when metadata exists.
- Cost display updates after chat, plan, refine, and meta actions.
- Unauthorized post access fails cleanly.
- Model settings changes reflect in generated requests.
Recommended Next Work
- Add a shared frontend
applyProviderMetadata()helper and call it for every AI response path. - Finish model registry adoption in active runtime paths and document any intentionally curated model presets.
- Move sidebar chat hydration off
/chat-history, or update that compatibility endpoint's contract and docblock. - Convert remaining raw cost hooks to
track_ai_cost()and add a static guard. - Run the live WordPress editor browser workflow pass.
Current Verdict
The ninth-pass implementation is substantially better and fixes the P0 runtime fatal. I would mark the ninth-pass blocker complete.
The plugin is close to leaving the audit-chain loop, but not fully closed. The remaining work is mostly consistency and verification: complete provider metadata UI coverage, finish model registry adoption, remove or formalize the deprecated chat-history dependency, and run the live editor pass.