268 lines
8.3 KiB
Markdown
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. |