CI on 61cf00c failed PHPUnit with "Call to undefined function
plugin_dir_path()" — the test required peptide-search-ai.php, which calls
plugin_dir_path() at top level (line 19) before any hook. Stubbing every
top-level WP function the plugin file touches was the wrong shape of fix.
Proper fix: move the upgrade logic into includes/class-psa-upgrade.php so
the test can require just the helper class, matching the pattern every
other includes/ module follows.
- New: includes/class-psa-upgrade.php with PSA_Upgrade::is_needed()
(pure) and PSA_Upgrade::maybe_run() (driver). OPTION_NAME and
DEFAULT_STORED_VERSION exposed as constants.
- peptide-search-ai.php: psa_admin_init() now calls PSA_Upgrade::maybe_run();
the inline helper functions and docblocks are removed.
- tests/bootstrap.php: loads class-psa-upgrade.php alongside the other
tested classes.
- tests/unit/UpgradeTest.php: rewritten against PSA_Upgrade; adds two
extra assertions on the constants for stability.
- ARCHITECTURE.md: refreshed to reference the class and its constants.
No behavioral change. The cost-tracker schema upgrade still runs once per
admin_init when PSA_VERSION advances past psa_db_version.
Agent-Session: cowork-qa-p1-fixes-20260414
Addresses the three P1 findings from QA baseline review of a8a0ce2:
1. uninstall.php: delete psa_db_version option on plugin removal so no
orphaned data is left behind — satisfies AGENT-OPERATING-STANDARD
teardown/uninstall DoD.
2. Extract psa_upgrade_needed( $stored, $current ) as a pure function and
add tests/unit/UpgradeTest.php covering fresh-install, same-version,
future-version, and older-version scenarios. The impure wrapper
psa_maybe_run_upgrades() now delegates the decision to the pure helper.
3. Document the psa_db_version option and the admin_init-triggered
upgrade mechanism in ARCHITECTURE.md (Options section), including
why admin_init, downgrade behavior, cleanup, and testability.
No behavioral change for end users — same upgrade semantics, just
testable and documented, with proper teardown.
Agent-Session: cowork-qa-p1-fixes-20260414
DeepSeek models on OpenRouter omit the usage object, causing all token
counts and costs to log as zero. Added character-based estimation
fallback (~3.75 chars/token), token_source column to distinguish
measured vs estimated data, and admin UI indicators (amber warnings,
~ prefix on estimates). Updated DeepSeek/Qwen pricing table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the WP-Cron-based re-enrichment with an AJAX polling approach
that processes one peptide per request. This bypasses WP-Cron entirely,
which is unreliable on Hostinger shared hosting with LiteSpeed + Cloudflare.
New files:
- includes/class-psa-batch-enrichment.php — AJAX endpoints for status + process
- assets/js/psa-batch-enrich.js — Admin progress bar UI with polling loop
The admin settings page now shows a "Re-enrich Peptides" button with live
progress bar, per-item log, and automatic retry on failure. Respects the
daily generation cap and monthly budget.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds [peptide_directory] shortcode with card grid, category taxonomy (8 terms),
search, pagination, detail modal, and /v1/compounds REST endpoint. Includes 9
new meta fields (half-life, stability, solubility, etc.), admin data tools for
migration/re-enrichment, integration hooks for cross-plugin extensibility,
dark mode support, and full uninstall cleanup. Refactors AI generator into
PSA_OpenRouter + PSA_KB_Builder classes. Adds PHPUnit tests for PostType and
Directory classes. Fixes QA findings: dead JS selector, renderError loading
state, numeric meta validation, prepared SQL in uninstall.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>