P0 security: - PRV_Gateway_Client: remove response body from RuntimeException (HTTP status only) - PRV_Capture_Writer: allowlist-only write (prompt/response text, never headers/auth) - Mandatory capture order: can_afford → probe → persist_result → update_row_cost → write_meta → capture_io - capture_io last and wrapped in swallowing try/catch New tables (SCHEMA_VERSION 3): - prv_call_meta: cost/metadata per call, kept indefinitely - prv_call_io: rendered prompt + raw response, pruned on retention window (default 90d) New classes: - PRV_Call_Meta_Table, PRV_Call_Io_Table: table schema + dbDelta - PRV_Capture_Writer: metadata + I/O write; security allowlist enforced - PRV_Prune_Cron: daily prv_daily_prune cron deletes aged prv_call_io rows only - PRV_Cost_Rollup_Query: MTD summary, model breakdown, drill-down, projection - PRV_Call_Log_Query: paginated + filtered call-log query + per-call I/O fetch - PRV_Costs_Page + PRV_Costs_Renderer: Costs admin sub-page (cap progress, bento, model table, drill-down) - PRV_Call_Log_Page + PRV_Call_Log_Table_Renderer: Call Log admin sub-page (filter bar, paginated table, WCAG AA pagination) - PRV_Call_Drawer_Renderer: non-modal complementary drawer (5 states: Normal/Pruned/Legacy/Failed/Loading) - PRV_Call_Drawer_Script: inline JS for drawer (300-line split from renderer) - PRV_Call_Detail_Ajax: wp_ajax_prv_call_detail AJAX handler - PRV_Admin_Page_Css: CSS provider (300-line split from PRV_Admin_Page) - PRV_Probe_Run_Executor: inner probe loop (300-line split from PRV_Probe_Runner) Updated: - PRV_Probe_Result: tokens_in/tokens_out params + getters - Both providers: report tokens_in/tokens_out from usage.prompt_tokens/completion_tokens - PRV_Probe_Runner: slimmed to lock+UUID+delegation; injects PRV_Capture_Writer - PRV_Config: get_io_retention_days(); PRV_IO_RETENTION_DEFAULT_DAYS constant - PRV_Upgrader/Activator/Deactivator/Plugin: register new tables, cron, pages, AJAX - Settings: retention days field + save in controller - uninstall.php: DROP both new tables, clear prv_daily_prune cron - Subnav 4-tab strip (Dashboard | Costs | Call Log | Settings) on all pages - ARCHITECTURE.md, CHANGELOG.md, CONTEXT.md, CONVENTIONS.md updated Tests: - test-capture-writer.php: write_meta, write_io, P0 security (401 record has no key/Bearer/sk-or-) - test-cost-audit.php: MTD reconciliation, projection, prune, forced capture_io exception, table drops Agent-Session: peptiderepo-geomonitor-v0.3.0-cost-audit
11 KiB
Context — Domain Glossary (PR Vision)
Version: 0.3.0 | Last updated: 2026-06-15
This file is the ubiquitous-language glossary for pr-vision. Every term below has a precise meaning within this codebase. AI agents and human contributors should use this terminology consistently.
Core domain terms
AI Visibility
Whether and where peptiderepo.com appears in AI assistant responses to peptide-related queries. The core metric this plugin measures.
Code identifiers: PRV_Ai_Visibility_Collector, PRV_Ai_Visibility_Panel, table column cited, option prefix prv_.
Probe
A single server-side LLM API call with a specific (peptide, intent, model) combination. The result is a PRV_Probe_Result value object.
Code identifiers: PRV_Probe_Provider::probe(), PRV_Probe_Runner::run().
Probe Run
A batch execution of all configured peptides × prompt_intents × models. Identified by a run_id (UUID). One cron tick = one run; the "Run now" button also triggers a run.
Code identifiers: PRV_Probe_Runner::run(), run_id column in prv_ai_visibility.
Peptide
A compound being tracked (e.g. BPC-157, TB-500). Stored as a slug + label pair in the prv_peptides option.
Code identifiers: prv_peptides option, peptide_slug + peptide_label columns.
Prompt Intent
A query template describing a searcher's intent (e.g. "what is {peptide}", "{peptide} reconstitution guide"). The {peptide} placeholder is replaced with the peptide's label at runtime.
Code identifiers: prv_prompt_intents option, prompt_intent column.
Citation / Cited
A probe is cited when peptiderepo.com appears in the LLM's source/citation list for that response. The cited column is TINYINT(1) (1 = cited, 0 = not cited).
Code identifiers: PRV_Citation_Detector::is_cited(), cited column, PRV_Probe_Result::is_cited().
Source Domains
The list of domains returned by the LLM as its sources for a given response (e.g. ["peptiderepo.com", "examine.com"]). Stored as JSON in source_domains.
Code identifiers: PRV_Citation_Detector::parse_domains(), PRV_Probe_Result::get_source_domains(), source_domains column.
Our Position
The 1-based rank of peptiderepo.com in the source domains list for a cited probe (NULL when not cited). Position 1 = we appear first.
Code identifiers: PRV_Citation_Detector::get_our_position(), our_position column, PRV_Probe_Result::get_our_position().
Visibility Score
A composite metric summarising peptiderepo.com's AI visibility for a run.
Formula:
base_score = cited_probes / total_probes
position_bonus = Σ(1 / our_position) for each cited probe / total_probes
visibility_score = round((base_score + position_bonus) / 2, 4)
- Range: [0.0, 1.0]. Score 1.0 requires 100% citation rate at position 1 for all probes.
- Why position-weighted? Being cited at position 1 is more valuable than position 10. The 1/position term gives a graduated bonus: position 1 = 1.0, position 2 = 0.5, position 5 = 0.2, etc.
- Stored: Computed from aggregate DB rows per run in
PRV_Ai_Visibility_Collector::compute_score(), not persisted as a column (recomputed on page load).
Code identifiers: PRV_Ai_Visibility_Collector::compute_score(), trendline data in collect().
Monthly Budget Cap
The maximum USD spend on LLM API calls in a calendar month. Stored in prv_monthly_budget_usd (default $5.00). The runner checks PRV_Cost_Ledger::can_afford() before each probe and stops gracefully when the cap is reached.
Code identifiers: PRV_Cost_Ledger, prv_monthly_budget_usd option, PRV_DEFAULT_MONTHLY_BUDGET_USD constant.
Provider
An implementation of PRV_Probe_Provider that wraps one LLM backend. v1 ships PRV_Perplexity_Provider (sonar) and PRV_OpenRouter_Provider (parameterised).
Code identifiers: interface-prv-probe-provider.php, PRV_Perplexity_Provider, PRV_OpenRouter_Provider.
Collector / Panel Seam
The extensibility mechanism: PRV_Data_Collector produces data; PRV_Dashboard_Panel renders it. Both are registered with PRV_Collector_Registry. v1 ships only the AI-visibility pair; future SEO categories add new pairs without touching the shell.
Code identifiers: interface-prv-data-collector.php, interface-prv-dashboard-panel.php, PRV_Collector_Registry.
Config Version
A monotonically incrementing integer (stored in the prv_config_versions option) that is bumped whenever the active probe configuration changes (models list, peptides list, or prompt intents). Each row in prv_ai_visibility is stamped with the config_version at the time it was recorded. Rows from a different config version are excluded from scoring to ensure comparability.
Code identifiers: PRV_Config_Version, bump_version_if_changed(), config_version column, prv_config_versions option.
Run Lock
A transient-backed mutex (prv_run_lock) that prevents concurrent probe runs. Acquired at the start of a run and released in a finally block. TTL is 1 hour to self-clear on fatal crash. Both the cron tick and the "Run now" button check is_locked() before dispatching.
Code identifiers: PRV_Run_Lock, acquire(), release(), is_locked(), transient prv_run_lock.
Model Registry
A versioned option (prv_models) storing the list of LLM models to probe. Each entry is a rich object with {id, provider, slug, enabled, note, health_status, health_probed, health_errors, health_run_id}. The registry migrates v0.1.x flat-string arrays to v2 schema on upgrade. CRUD is exposed on the Settings page.
Code identifiers: PRV_Model_Registry, run_migration_v2(), prv_models option, PRV_SCHEMA_VERSION constant.
Run Health
A per-model health status derived from the most recent probe run outcomes. Values: healthy (probes succeeded), retired (zero rows, errors occurred), disabled (model not enabled), unknown (not yet run). Displayed as a badge in the Model Manager table. Updated by PRV_Model_Registry::update_health() at end of each run.
Code identifiers: health_status, health_probed, health_errors, health_run_id fields; PRV_Model_Registry::update_health(); render_health_badge().
Projected Cost
The estimated monthly spend (in USD) based on the current configuration: enabled_models × peptides × intents × $0.005/probe × runs_per_month. Displayed on the Settings page as a cost inset. The over_cap flag is shown with aria-live="polite" when the projected cost would exceed the monthly budget.
Code identifiers: PRV_Config::get_projected_cost(), per_run_usd, per_month_usd, probe_count, over_cap return keys.
Config-version Stamp
The act of recording the active config_version integer on each prv_ai_visibility row at insert time. Enables retrospective filtering: only rows with config_version = active_version are included in current-period scoring, preventing cross-config score pollution.
Code identifiers: config_version column in prv_ai_visibility, PRV_Config_Version::get_active_version().
Truncation State
When the monthly budget cap is reached mid-run, prv_last_run_truncated is set to 1. This surfaces on the Settings page as a notice: "Last run was truncated by the monthly budget cap." The flag is cleared on the next successful full run. Probes after the cap are skipped (not errored) and counted in skipped_budget.
Code identifiers: prv_last_run_truncated option, PRV_Cost_Ledger::can_afford(), skipped_budget count, truncated flag in run counts.
GEO
Generative Engine Optimization — the practice of improving a brand's visibility in AI-generated responses. This plugin is the measurement instrument for peptiderepo.com's GEO program.
Proxy Metric
The plugin's scores are API-probe measurements, not real-world consumer LLM usage. The admin page labels these explicitly as "a directional proxy, not the consumer ChatGPT/Gemini apps."
Code identifiers: PRV_Ai_Visibility_Panel::render_proxy_note().
MTD Cost
Month-to-date spend in USD, summed from the cost_usd column for rows in the current calendar month.
Code identifiers: PRV_Cost_Ledger::get_month_to_date_usd().
Key Store (v0.2.3)
The subsystem that manages the OpenRouter API key with a precedence chain and encrypted-at-rest storage. Precedence: PRV_OPENROUTER_API_KEY wp-config constant (highest) → encrypted admin option prv_provider_key_enc → none. All key reads by providers and AJAX handlers route through PRV_Key_Store::get_key(). The plaintext key is never stored in any option, log, or client-side surface.
Code identifiers: PRV_Key_Store, PRV_Key_Store::get_key(), PRV_Key_Store::store_key(), PRV_Key_Store::clear_key(), PRV_Key_Store::get_source(), prv_provider_key_enc option.
Write-only Key UI (v0.2.3)
The Settings page section that allows the operator to set/replace/clear the API key without the key ever being rendered in the browser. The password input always renders empty. The UI shows only the key source (wp-config / admin / not set) and the last-run health state. The key value is never output to page HTML, JS, REST responses, or logs.
Code identifiers: PRV_Key_Manager_Renderer, PRV_Key_Test_Ajax, PRV_Settings_Controller::handle_key_set(), PRV_Settings_Controller::handle_key_remove().
Encryption Key (v0.2.3)
The symmetric key used to encrypt/decrypt prv_provider_key_enc. Derived via SHA-256 from AUTH_KEY + SECURE_AUTH_KEY (or wp_salt() fallback) — environment-specific and never stored. Derived fresh at every encrypt/decrypt call.
Code identifiers: PRV_Key_Store::derive_encryption_key(), PRV_Crypto_Helper::encrypt(), PRV_Crypto_Helper::decrypt().
Call Meta / Call Log
The per-call audit trail introduced in v0.3.0. Every LLM probe call produces a call metadata row (prv_call_meta) kept indefinitely, and a call I/O row (prv_call_io) retained for a configurable window.
Code identifiers: PRV_Call_Meta_Table, PRV_Call_Io_Table, PRV_Capture_Writer, PRV_Call_Log_Query.
Capture Writer
The PRV_Capture_Writer class that writes call metadata + I/O rows after a probe. Implements a strict allowlist: stores rendered prompt text, response text, model, tokens, cost — NEVER headers, Authorization, or any raw HTTP request object.
Code identifiers: PRV_Capture_Writer::write_meta(), PRV_Capture_Writer::write_io().
Retention Window
The configurable number of days raw prompt + response text is kept in prv_call_io before the daily prune cron deletes it. Default 90 days. Cost/metadata in prv_call_meta is kept indefinitely.
Code identifiers: PRV_Config::get_io_retention_days(), prv_io_retention_days option, PRV_Prune_Cron::prune_now().
Detail Drawer
A non-modal, keyboard-accessible panel (role="complementary") on the Call Log page that shows the exact rendered prompt + raw response for any selected call. Five states: Normal, Pruned, Legacy/not-captured, Failed, Loading. Focus-managed: opens to close button, Esc closes and returns focus to the triggering row, no tab-trap.
Code identifiers: PRV_Call_Drawer_Renderer, PRV_Call_Drawer_Script, PRV_Call_Detail_Ajax.
Capture Ordering (P0)
The mandatory sequence within each probe iteration: can_afford → probe → persist_result → update_row_cost → write_meta → capture_io. capture_io is always last and wrapped in a swallowing try/catch so a write failure can never reach the probe path or corrupt cap accounting.
Code identifiers: PRV_Probe_Run_Executor::probe_one().