Files
wp-agentic-writer/docs/DEFINITION_OF_DONE.md

8.3 KiB

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.

// 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.

// 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

// 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

// 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

// 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:

// 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.