number_format() in PHP 8.3 strictly requires int|float; $wpdb->get_var()
returns string|null. Cast $total to (int) at point of assignment in
admin/partials/articles-list.php to fix HTTP 500 on Articles admin page.
Also add PHPUnit test covering the string->int cast contract.
Fixes#31. Version bump 2.5.0 -> 2.5.1.
Agent-Session: fix-articles-500-20260617
- Replace 4 short ternary operators (?:) with explicit conditionals in Cost_Tracker
- Move declare(strict_types=1) after file-level docblocks in 3 template files
(PHPCS requires docblock immediately after opening PHP tag)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New Cost_Tracker class: logs every API call (model, tokens, cost), enforces
monthly budgets with hard-stop mode, provides aggregated reporting
- New llm_costs database table with indexes on created_at, model, operation
- Modified LLM class: call_openrouter_with_usage() extracts token usage from
OpenRouter responses; budget gate checks before each API call
- Admin settings: monthly budget (USD), enforcement mode (disabled/warn/hard-stop),
cost log retention period
- Admin cost dashboard: budget progress bar, daily cost chart (Chart.js),
per-model and per-operation breakdowns, recent API call log
- PHPUnit tests: 16 tests covering cost calculation, pricing lookups,
budget enforcement logic, and model validation
- Updated ARCHITECTURE.md with new table schema, data flow, and key decisions
- Updated CONVENTIONS.md with "how to add cost tracking for a new operation"
- Version bump to 2.4.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add bulk and per-row article deletion with AJAX handler, confirmation
dialogs, and cascading cleanup of click analytics via foreign keys.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all AI thumbnail generation infrastructure (too expensive,
poor results) and rewrite the public-facing article feed as a React
SPA mounted via WordPress shortcode.
Changes:
- Remove thumbnail generation, OG scraping, and image download code
from fetcher, LLM, and admin classes
- Replace server-rendered PHP templates with React component
(PeptideNewsFeed.jsx) using WordPress-bundled React/ReactDOM
- Add Babel build pipeline for JSX transpilation
- Update REST API to serve ai_summary instead of thumbnail fields
- Redesign public CSS: clean card layout, loading skeletons,
dark mode, responsive, no thumbnail imagery
- Remove dead admin settings (llm_image_model, thumbnail_fallback)
- Fix call_openrouter() visibility for Content Filter cross-class use
- Bump version to 1.3.0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DuckDuckGo's HTML search endpoint now requires vqd session tokens,
making server-side search-based URL resolution unreliable. Simplified
the thumbnail pipeline:
- OG scrape only for non-aggregator URLs (direct publisher pages)
- AI image generation via OpenRouter for aggregator articles (Google News)
- Added Image Model settings field in admin UI
- Added thumbnail_local column for AI-generated images
- Updated public/admin display to check thumbnail_local as fallback
- Removed all DuckDuckGo search code (find_article_url_via_search,
extract_ddg_url, resolve_article_for_scraping)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>