# WP Agentic Writer - Definition of Done ## Purpose This contract prevents the "fix A, break B" cycle by ensuring every change to chat, planning, writing, refinement, context, provider, or cost has explicit ownership and accountability. --- ## Contract Checklist For every PR touching these domains: chat, planning, writing, refinement, context, provider, cost ### 1. Storage Layer Declaration **Required:** State which storage layer is authoritative for the change. | State Type | Authoritative Storage | |------------|----------------------| | Conversation messages | `wpaw_conversations.messages` (via Context Service) | | Article outline/plan | `post_meta._wpaw_plan` (via Context Service) | | Per-post configuration | `post_meta._wpaw_post_config` (via Context Service) | | User preferences | `wp_agentic_writer_settings` | | Cost records | `wpaw_cost_tracking` | | Image recommendations | `wpaw_images` | | Session state | `wpaw_conversations` | If the change touches multiple storage layers, explain why and ensure they stay in sync. ### 1a. Context Service Usage **Required for all generation paths:** Use `WP_Agentic_Writer_Context_Service` as the unified interface. ```php // Get context (single source of truth) $context_service = WP_Agentic_Writer_Context_Service::get_instance(); $context = $context_service->get_context($session_id, $post_id); // Save messages to session table $context_service->save_messages($session_id, $messages); // Save plan to post meta $context_service->save_plan($post_id, $plan); // Save config to post meta $context_service->save_post_config($post_id, $config); ``` **Rules:** - Conversation messages → always use `save_messages()` or `add_message()` (writes to session table) - Plan/Config → use `save_plan()` / `save_post_config()` (writes to post meta) - Legacy `_wpaw_chat_history` post meta → migrate on first access via `migrate_legacy_chat_history()` ### 2. Provider Transparency **Required:** Include provider/model metadata in the response. ```php // Every AI response must include: $result = [ 'content' => '...', 'provider' => 'openrouter', // actual provider used 'model' => 'anthropic/claude-3.5-haiku', // actual model used 'cost' => 0.0025, 'warnings' => [] // any issues (fallback used, etc) ]; ``` ### 3. Cost Record Integrity **Required:** Every API request must update cost records intentionally. - Successful calls → record actual cost - Failed calls → record attempt with error status - Skipped calls → no record needed - Never silently fail to record costs ### 4. Workflow Test Requirement **Required:** Test at least one complete workflow path. Minimum paths to test: 1. **Chat → Plan → Write** (happy path) 2. **Write → Stop → Resume** (pause/resume) 3. **Plan → Clear Context → New Plan** (context reset) For each path, verify: - State persists correctly - Cost records are accurate - Errors are handled gracefully ### 5. No Double Source of Truth **Required:** The same state must not exist in two places. - If session table is authoritative, don't also trust post meta for the same data - If you copy data for performance, document the sync mechanism - If two sources diverge, one must win (document which) --- ## Storage Layer Map ``` ┌─────────────────────────────────────────────────────────────┐ │ FRONTEND (sidebar.js) │ │ React State ← localStorage ← Session Table ← Post Meta │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ BACKEND (PHP) │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Sessions │ │ Post Meta │ │ Settings/Cost │ │ │ │ wpaw_conv │ │ _wpaw_plan │ │ wpaw_cost_tracking │ │ │ │ │ │ _wpaw_* │ │ wp_agentic_writer_* │ │ │ │ Authority: │ │ Authority: │ │ Authority: │ │ │ │ Messages │ │ Plan/Config │ │ Settings/Costs │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` **Priority Rules:** 1. `wpaw_conversations` is authoritative for conversation messages 2. `post_meta` is authoritative for article plan and per-post config 3. `wpaw_cost_tracking` is authoritative for usage costs 4. `wp_agentic_writer_settings` is authoritative for plugin settings --- ## Error Handling Contract ### For AI/Provider Errors ```php // Always return meaningful errors, not silent failures if ( is_wp_error( $result ) ) { return [ 'success' => false, 'error_code' => $result->get_error_code(), 'error_message' => $result->get_error_message(), 'provider' => $actual_provider_used ?? 'unknown', 'can_retry' => is_retryable_error( $result ) ]; } ``` ### For Database Errors ```php // Tables must exist before operations; verify and create if needed $image_manager->ensure_tables(); // Call this before any DB operation if ( is_wp_error( $check ) ) { return $check; // Return WP_Error with clear message } ``` ### For Validation Errors ```php // Validate early, fail clearly if ( empty( $post_id ) ) { return new WP_Error( 'missing_post_id', 'Post ID is required', 400 ); } ``` --- ## Provider Selection Contract ### Explicit Fallback If a provider fails and you fall back to another: 1. Log the fallback with both provider names 2. Include `warnings: ['Provider X unavailable, fell back to Y']` in response 3. UI must show actual provider used, not selected provider ### Provider Health Check Before expensive operations, optionally verify provider is reachable: ```php // In provider-manager.php, expose health status public static function get_provider_health( $provider_name ) { $provider = self::get_provider_instance( $provider_name, 'chat' ); if ( ! $provider || ! $provider->is_configured() ) { return ['status' => 'unconfigured']; } // Optional: test reachability return ['status' => 'ready']; } ``` --- ## Migration Safety Contract When adding new database tables or fields: 1. Always use `CREATE TABLE IF NOT EXISTS` 2. Provide migration for existing installations 3. Handle missing tables gracefully (create on demand) 4. Version each table independently --- ## Security Contract ### Session Access - Every session endpoint must verify ownership - Users can only access their own sessions - For post-linked sessions, verify `current_user_can('edit_post', $post_id)` ### Input Validation - Sanitize all inputs before database operations - Use WordPress sanitization functions - Never trust user-provided data ### Output Escaping - All output to frontend must be escaped appropriately - Use `wp_json_encode()` for JSON - Use `esc_html()`, `esc_attr()` for text --- ## Testing Requirements ### Before Merging - [ ] PHP syntax check passes - [ ] JS syntax check passes - [ ] All new functions have docblocks - [ ] No hardcoded credentials or API keys - [ ] Error paths are tested (even if manually) ### For New Features - [ ] At least one workflow path tested end-to-end - [ ] Error handling documented - [ ] Cost implications considered - [ ] Storage layer declaration written --- ## Changelog Policy When making changes, update `CHANGELOG.md` with: ``` ## [Unreleased] ### Added - Feature description ### Changed - Behavior change ### Fixed - Bug fix description ### Security - Security fix description ``` Format: Keep unreleased at top, use semantic versioning for releases.