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

268 lines
8.3 KiB
Markdown

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