Medoria AI Search App - Compact Operational Handoff 1. Project Identity - Standalone PHP admin app. - Not a Joomla component. - Joomla integration is planned later via secure bridge / custom endpoint. - Do not do direct inserts into the Joomla DB. 2. Stack - PHP 8.3 - MySQL - utf8mb3_general_ci - Vanilla JS - AJAX where needed - cPanel / LiteSpeed - OpenAI API - No frameworks 3. Core Structure - `/admin` - `/ajax` - `/includes` - `/services` - `/repositories` - `/templates` - `/assets/css` - `/assets/js` - `/storage/logs` - `/docs` 4. Working Rules - Step by step. - One feature at a time. - No scope drift. - No refactors unless explicitly requested. - Small, targeted changes only. - Do not touch unrelated files. - If the user says `modify only X`, stay strictly inside X. - Apply changes directly in the workspace, not only as snippets. - If old chat state conflicts with disk, source of truth is the actual current workspace. 5. Engineering Rules - `declare(strict_types=1);` - Security first. - Validate everything. - No frameworks. - Explicit safe DB access with prepared statements. - Avoid schema guessing when not confirmed. - JSON-only responses for AJAX endpoints. - No API key exposure. - No raw debug dumps in final working state. 6. Environment Reality - Windows environment is fragile. - `apply_patch` has repeatedly failed in this workspace. - PowerShell fallback writes are often needed. - Readback verification after writes is mandatory. - Keep UTF-8 without BOM. - PowerShell output may show mojibake for Greek even when files are actually UTF-8. - `php` CLI and `git` may not be reliably available in PATH. - `docs/chats.md` may render as mojibake in terminal output; trust file content on disk. 7. Workflow / Status Model - Workflow: - Search -> Accept -> Pending -> Edit -> Finalize -> Ready -> Transfer -> Done - Status rules: - `pending` is set automatically on Accept. - `ready` is set automatically after edit/save. - `done` is set automatically after Joomla transfer. - `rejected` is only for rejection flow. - Allowed manual actions: - Accept - Reject - Not allowed: - Manual status dropdown - Mark ready button - Mark done button - Manual status editing 8. Confirmed Schema / Data Notes - `wm_discovered_articles` confirmed fields include: - `joomla_author` - `joomla_category` - `content` - `meta_description` - `alias` - `finalized_at` - `tags` - `image_main_filename` - `image_thumb_filename` - `image_keyword` - `image_provider` - `image_provider_image_id` - `image_source_url` - `image_photographer` - Historical ambiguity exists around `source_url` vs `article_url`, especially near finalize/apply flows. - Feed subsystem confirmed tables: - `wm_feed_sources` - `wm_feed_items` - `wm_feed_items.translated_title` exists. - `wm_admin_notices` exists. - Settings use table `settings` with `setting_key` / `setting_value` and `INSERT ... ON DUPLICATE KEY UPDATE` pattern. 9. Shared Admin Shell - Shared layout files: - `templates/admin-layout-start.php` - `templates/admin-layout-end.php` - Shared branding/navigation across admin pages. - `assets/css/admin.css` is the central admin styling file. - `admin/login.php` has UI refresh only; core logic should remain unchanged. 10. Current Stable Files / Areas - `admin/settings.php` - full settings screen working - OpenAI settings/models/prompts - Joomla mapping settings - feed frequency setting - refine title/meta prompt settings - image provider settings/test UI exists - image processing settings section exists - `admin/article-edit.php` - main edit workspace - Quill + HTML toggle - save flow -> `ready` - finalize integration exists - refine integration exists - custom tags UI with hidden authoritative input - image search UI, preview modal, select flow, remove image action exist - selected-image summary includes provider/meta and local thumb preview area - manual upload area exists at the top of the Image section - provider badges/modal provider info support multi-provider search results - `ajax/finalize-article.php` - real finalize flow exists - needs caution and runtime verification - `admin/search.php` - DB-backed review workspace over `wm_search_items` - row apply/reject - bulk apply/delete - cleanup support - pagination 20/page - `admin/applied.php` - main applied/articles workspace - filters / summaries / badges / delete actions - bulk finalize foundation exists - Greek translated title is clickable to edit - `admin/feed.php` - focused on stored feed items workflow - accept / reject / bulk actions / cleanup exists - header/progress UI exists - `admin/sources.php` - tabbed Sources page - `Article Sources` tab - `Feed Sources` tab with Add Feed Source, Feed Sources table, Scheduler Overview 11. Settings State - `admin/settings.php` persists and serves: - `openai_api_key` - `model_search` - `model_translate` - `model_finalize` - `prompt_search` - `prompt_translate` - `prompt_finalize` - `max_articles_per_source` - `joomla_authors` - `joomla_categories` - `default_joomla_author` - `default_joomla_category` - `feed_crawl_frequency_per_day` - `refine_title_prompt_1/2/3` - `refine_meta_prompt_1/2/3` - `pexels_api_key` - `pixabay_api_key` - `pexels_per_page` - `image_main_width` - `image_main_height` - `image_thumb_width` - `image_thumb_height` - `image_webp_quality` - Dynamic model loading from OpenAI Models API exists with fallback key logic. - Image provider availability logic already exists in helpers: - empty `pexels_api_key` => Pexels disabled - empty `pixabay_api_key` => Pixabay disabled - `ajax/save-settings.php` exists and saves image-processing settings with validation/fallback defaults. - Image-processing defaults: - `image_main_width = 1200` - `image_main_height = 675` - `image_thumb_width = 600` - `image_thumb_height = 600` - `image_webp_quality = 85` 12. Article Edit / Finalize State - `admin/article-edit.php` editable fields save through main form: - `translated_title` - `alias` - `content` - `meta_description` - `tags` - `joomla_author` - `joomla_category` - Save flow: - saves fields - sets `status = 'ready'` - updates `updated_at` - Tags UI: - `tagsHidden` is authoritative - rendered chips - add/remove behavior - Finalize fills fields through AJAX. - Finalize caution: - current flow has historical `source_url` vs `article_url` ambiguity - OpenAI parsing/runtime edge cases remain a risk - Current image picker state in `admin/article-edit.php`: - Image section is below Tags. - Manual upload appears before search controls. - Upload area supports drag and drop and click-to-upload for one image at a time. - Search input opens empty by default. - Search filters: keyword, Pexels `orientation`, `size`, `color`. - Search is AJAX via `ajax/search-article-images.php`. - Selection/removal/upload uses `ajax/select-article-image.php`. - Results grid targets 4 columns on desktop. - Search pagination exists via AJAX. - Preview modal exists. - Preview modal supports Previous / Next within the currently loaded result set. - Preview modal Select action reuses the same selection flow. - Grid cards and preview modal show provider using the returned provider field. - Search currently merges Pexels + Pixabay results in a unified frontend-compatible format. - Select flow must send the direct image file URL for processing. - `image_source_url` remains the human/provider page URL when available. - Selected image summary is shown only when there is real saved local image state. - Selected image summary uses local thumb preview only, never remote provider preview URLs. - Remove Image button exists and clears the selected image via AJAX. - Current image processing / selection backend state: - `ajax/select-article-image.php` supports select, remove, and manual upload actions. - Provider mode accepts `pexels` and `pixabay` and must remain unchanged. - Manual upload mode uses `$_FILES` on the same endpoint. - No image-related DB fields are saved before local processing succeeds. - Processing uses `image_url` in provider mode and uploaded temp file in upload mode. - Old local image files are deleted only after successful new processing + successful DB update. - Manual upload size limit is 25 MB (`26214400` bytes). - Oversized upload message is: `Image is too large to process. Maximum allowed size is 25 MB.` - Manual upload logs include start info, dimensions, stage-based failure info, and max-size logging. - Selection/upload flow logs to `storage/logs/image-processing.log`. 13. Search State - Search is DB-backed on `wm_search_items`. - The page is a review workspace, not only temporary AJAX output. - Features/history that matter: - source-aware search run - stored items table - row apply/reject - bulk apply/delete - cleanup old items - stricter article candidate filtering - Greek-safe URL normalization/validation - pagination 20/page - Relevant foundations: - `services/ArticleLinkFilter.php` - `services/ArticleUrlNormalizer.php` - `services/SearchService.php` 14. Feed State - Feed source management lives in `admin/sources.php` Feed tab. - `admin/feed.php` is focused on stored feed items. - Feed subsystem includes: - feed items list - accept / reject - bulk apply / bulk delete - cleanup old items - sequential progress UI / summary - Scheduler foundation exists, but not every production cron edge case has been verified. 15. Sources Page State - `admin/sources.php` is important and has repeated recent history. - Stable structure: - tabbed page with `Article Sources` and `Feed Sources` - Feed tab contains Add Feed Source, Feed Sources table, Scheduler Overview - Article Source form keeps client-side URL normalization for non-ASCII path handling. - Strong rule: - if a request is only about the Article Sources table, do not touch the Feed Sources table. - If working there, always read first: - `admin/sources.php` - `assets/css/admin.css` 16. Services / Foundations That Already Exist - `services/ArticleScraper.php` - scraper/fetch/extraction foundation - `services/ArticleLinkFilter.php` - Greek-safe pattern matching / stricter candidate filtering - `services/ArticleUrlNormalizer.php` - Greek-safe normalization/validation for article URLs - `services/SearchService.php` - search-side filtering/logging/counters - `services/ImageSearchService.php` - reads `pexels_api_key`, `pixabay_api_key`, validated `pexels_per_page` - supports Pexels search with optional filters: `orientation`, `size`, `color` - supports Pixabay search in fail-safe mode alongside Pexels - merges providers without breaking Pexels responses - returns unified item shape compatible with frontend - logs request/result/error summary to `storage/logs/image_search.log` - `services/ImageProcessingService.php` - remote image download via cURL - uploaded-file processing via the same shared pipeline - temp file handling - GD load / resize / center crop - input support for jpg/jpeg/png/webp - settings-driven output sizes/quality with defaults - timestamped WebP main/thumb filenames - provider-aware debug logging to `storage/logs/image-processing.log` - manual upload stage-based diagnostics logging - Feed crawler/scheduler foundations exist. - Cleanup services for Search/Feed temp items exist. - Reuse existing service paths instead of building parallel logic. 17. Open Risks - `ajax/finalize-article.php` - `source_url` vs `article_url` ambiguity - OpenAI response parsing/runtime edge cases - `admin/article-edit.php` - large file with a lot of behavior - image picker/search/select/remove/upload/local-preview flow still needs practical browser verification - `admin/sources.php` - repeated recent table/UI tweaks - `assets/css/admin.css` - central file, easy to break multiple pages with broad selectors - `services/ImageProcessingService.php` - provider direct-file download path still needs runtime confirmation with live results/logs - large but valid uploads still need practical runtime confirmation in the real environment - Multi-provider image search/select path needs end-to-end runtime confirmation with actual Pixabay results. 18. Do Not Touch Without Need - Do not broad-refactor `assets/css/admin.css`. - Do not change Feed Sources table when the request is only about Article Sources. - Do not guess DB schema details when not confirmed. - Do not redesign pages if the request is only for a local fix. - Do not alter status workflow rules unless explicitly requested. - Do not introduce direct Joomla DB insertion. - Do not modify `ajax/search-images.php` unless the task is specifically about the settings-side tester. - Do not modify `services/ImageSearchService.php` unless the task is specifically about image search backend behavior. - Do not mix article image picker work with unrelated UI sections. - Do not modify `services/ImageProcessingService.php` during UI-only tasks unless the request explicitly needs backend image processing changes. 19. Still Not Done - No actual Joomla transfer implementation yet. - No completed secure Joomla bridge yet. - No real `done` automation via production transfer yet. - Alias uniqueness validation is not complete. - Meta description hardening is not complete. - Full HTML sanitization policy for saved AI HTML is not complete. - Image system still needs practical runtime confirmation for: - direct Pexels file URL selection - direct Pixabay `full_url` selection - local image download success on real results - manual upload success for larger but valid files under 25 MB - stable remove/reselect/reopen behavior - local thumb preview behavior after real select/remove/upload cycles - Full browser/runtime verification of recent admin UI changes is still pending. 20. Best Next-Chat Operating Pattern - Read the actual current files first. - Stay inside the exact requested scope. - If the request is CSS/layout only, do not touch logic/query/action code. - If the request is file-scoped, touch only that file unless explicitly expanded. - Reuse existing services/foundations where possible. - After writes, always do readback verification. - If a file changed many times in recent chats, trust only the file on disk. - For article image work, read both UI and endpoints before changing behavior. - If debugging image download or upload failures, check `storage/logs/image-processing.log` and `storage/logs/image_search.log` early. - When `docs/chats.md` looks corrupted in terminal output, trust the disk file and this compact handoff. 21. Most Likely Useful Read-First Files - `admin/article-edit.php` - `ajax/select-article-image.php` - `services/ImageProcessingService.php` - `services/ImageSearchService.php` - `ajax/search-article-images.php` - `ajax/finalize-article.php` - `admin/sources.php` - `admin/search.php` - `admin/feed.php` - `admin/applied.php` - `admin/settings.php` - `ajax/save-settings.php` - `storage/logs/image-processing.log` - `storage/logs/image_search.log` 22. Short Operational Memory - Standalone PHP admin app, no framework, no direct Joomla DB insert. - Step-by-step, small scoped changes, no unrelated refactors. - Windows environment is fragile; verify every write. - `admin/sources.php` = tabbed Sources page. - `admin/feed.php` = stored feed items workflow. - `admin/search.php` = DB-backed review workspace. - `admin/article-edit.php` = main edit/refine/finalize/image-picker/manual-upload workspace. - `ajax/finalize-article.php` needs caution, especially `source_url` vs `article_url`. - `services/ImageSearchService.php` = current multi-provider image search foundation. - `services/ImageProcessingService.php` = local/remote image processing foundation with settings-driven WebP output and manual upload diagnostics logging. - `ajax/search-article-images.php` and `ajax/select-article-image.php` power the article image picker flow. - Current image picker supports manual upload, grid search, AJAX pagination, preview modal, prev/next navigation, card Select, modal Select, selected-image summary, local thumb preview, and Remove Image. - Provider select must use direct image file URL for processing; page URL is only reference. - Manual upload max is 25 MB and returns a clear limit message when exceeded. - Selected image preview in edit page must use the local thumb file only, never remote provider preview URLs. - When in doubt: read actual files first, change only the requested area, verify after write.