PR Vision v0.1.1: rename from peptide-geo-monitor + P2 fixes

- Exhaustive rename: PGM_ -> PRV_, pgm_ -> prv_, text domain and
  slug peptide-geo-monitor -> pr-vision, admin menu GEO Monitor ->
  PR Vision, main file peptide-geo-monitor.php -> pr-vision.php,
  DB table pgm_ai_visibility -> prv_ai_visibility.
- P2-A: replace ltrim($host,'www.') character-mask with
  str_starts_with/substr prefix strip in PRV_Citation_Detector.
  Adds test coverage for wikipedia.org, webmd.com survival.
- P2-B: drop continue-on-error: true from PHPCS CI step;
  WordPress Coding Standards now gates the build.
- P2-C: remove dead in-run cache from PRV_Probe_Runner::run();
  each (peptide, intent, model) triplet is visited once per run,
  cache hit is structurally impossible.
- Version bump 0.1.0 -> 0.1.1 + CHANGELOG [0.1.1] entry.

Agent-Session: pr-vision rename v0.1.1
This commit is contained in:
peptiderepo
2026-06-13 09:32:56 +00:00
parent 46fda89e18
commit 60ae52663c
39 changed files with 852 additions and 830 deletions

View File

@@ -2,7 +2,7 @@
declare(strict_types=1);
/**
* AI-visibility dashboard panel — renders the GEO Monitor admin page.
* AI-visibility dashboard panel — renders the PR Vision admin page.
*
* Renders four sections:
* 1. Proxy-metric disclaimer note.
@@ -10,31 +10,31 @@ declare(strict_types=1);
* 3. Per-peptide standings table (cited, position, top competitor domains).
* 4. MTD cost vs cap + last-run time.
*
* All output is escaped. Chart.js is enqueued via PGM_Admin_Page.
* All output is escaped. Chart.js is enqueued via PRV_Admin_Page.
*
* Who triggers: PGM_Admin_Page::render_page() via PGM_Collector_Registry.
* Dependencies: PGM_Ai_Visibility_Collector (data format contract).
* Who triggers: PRV_Admin_Page::render_page() via PRV_Collector_Registry.
* Dependencies: PRV_Ai_Visibility_Collector (data format contract).
*
* @see interface-pgm-dashboard-panel.php — Interface this implements.
* @see class-pgm-ai-visibility-collector.php — Produces the $data array.
* @see class-pgm-admin-page.php — Enqueues Chart.js; calls render().
* @package PeptideGeoMonitor
* @see interface-prv-dashboard-panel.php — Interface this implements.
* @see class-prv-ai-visibility-collector.php — Produces the $data array.
* @see class-prv-admin-page.php — Enqueues Chart.js; calls render().
* @package PrVision
*/
class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
class PRV_Ai_Visibility_Panel implements PRV_Dashboard_Panel {
/**
* {@inheritDoc}
*
* @param array<string, mixed> $data Payload from PGM_Ai_Visibility_Collector.
* @param array<string, mixed> $data Payload from PRV_Ai_Visibility_Collector.
*
* @return void
*/
public function render( array $data ): void {
$trendline = is_array( $data['trendline'] ?? null ) ? $data['trendline'] : array();
$standings = is_array( $data['standings'] ?? null ) ? $data['standings'] : array();
$last_run_at = isset( $data['last_run_at'] ) && $data['last_run_at'] ? esc_html( (string) $data['last_run_at'] ) : esc_html__( 'Never', 'peptide-geo-monitor' );
$last_run_at = isset( $data['last_run_at'] ) && $data['last_run_at'] ? esc_html( (string) $data['last_run_at'] ) : esc_html__( 'Never', 'pr-vision' );
$mtd_cost = isset( $data['mtd_cost_usd'] ) ? (float) $data['mtd_cost_usd'] : 0.0;
$cap = isset( $data['monthly_cap_usd'] ) ? (float) $data['monthly_cap_usd'] : PGM_DEFAULT_MONTHLY_BUDGET_USD;
$cap = isset( $data['monthly_cap_usd'] ) ? (float) $data['monthly_cap_usd'] : PRV_DEFAULT_MONTHLY_BUDGET_USD;
$this->render_proxy_note();
$this->render_meta_bar( $last_run_at, $mtd_cost, $cap );
@@ -46,7 +46,7 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
* {@inheritDoc}
*/
public function get_title(): string {
return __( 'AI Visibility', 'peptide-geo-monitor' );
return __( 'AI Visibility', 'pr-vision' );
}
/**
@@ -55,9 +55,9 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
* @return void
*/
private function render_proxy_note(): void {
echo '<div class="notice notice-info pgm-proxy-note"><p>';
echo '<strong>' . esc_html__( 'Note:', 'peptide-geo-monitor' ) . '</strong> ';
echo esc_html__( 'Scores are measured via API probes — a directional proxy, not the consumer ChatGPT/Gemini apps (different retrieval, personalisation, and system prompts).', 'peptide-geo-monitor' );
echo '<div class="notice notice-info prv-proxy-note"><p>';
echo '<strong>' . esc_html__( 'Note:', 'pr-vision' ) . '</strong> ';
echo esc_html__( 'Scores are measured via API probes — a directional proxy, not the consumer ChatGPT/Gemini apps (different retrieval, personalisation, and system prompts).', 'pr-vision' );
echo '</p></div>';
}
@@ -72,9 +72,9 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
*/
private function render_meta_bar( string $last_run_at, float $mtd_cost, float $cap ): void {
$pct = $cap > 0 ? min( 100.0, round( $mtd_cost / $cap * 100, 1 ) ) : 0;
echo '<div class="pgm-meta-bar">';
echo '<span class="pgm-meta-item"><strong>' . esc_html__( 'Last run:', 'peptide-geo-monitor' ) . '</strong> ' . esc_html( $last_run_at ) . '</span>';
echo '<span class="pgm-meta-item"><strong>' . esc_html__( 'MTD cost:', 'peptide-geo-monitor' ) . '</strong> $' . esc_html( number_format( $mtd_cost, 4 ) ) . ' / $' . esc_html( number_format( $cap, 2 ) ) . ' (' . esc_html( $pct ) . '% of cap)</span>';
echo '<div class="prv-meta-bar">';
echo '<span class="prv-meta-item"><strong>' . esc_html__( 'Last run:', 'pr-vision' ) . '</strong> ' . esc_html( $last_run_at ) . '</span>';
echo '<span class="prv-meta-item"><strong>' . esc_html__( 'MTD cost:', 'pr-vision' ) . '</strong> $' . esc_html( number_format( $mtd_cost, 4 ) ) . ' / $' . esc_html( number_format( $cap, 2 ) ) . ' (' . esc_html( $pct ) . '% of cap)</span>';
echo '</div>';
}
@@ -86,10 +86,10 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
* @return void
*/
private function render_trendline( array $trendline ): void {
echo '<div class="pgm-card"><h2>' . esc_html__( 'Visibility Score — Trend', 'peptide-geo-monitor' ) . '</h2>';
echo '<div class="prv-card"><h2>' . esc_html__( 'Visibility Score — Trend', 'pr-vision' ) . '</h2>';
if ( empty( $trendline ) ) {
echo '<p>' . esc_html__( 'No probe runs recorded yet. Click "Run now" to collect the first data point.', 'peptide-geo-monitor' ) . '</p></div>';
echo '<p>' . esc_html__( 'No probe runs recorded yet. Click "Run now" to collect the first data point.', 'pr-vision' ) . '</p></div>';
return;
}
@@ -103,9 +103,9 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
$labels_json = wp_json_encode( $labels );
$scores_json = wp_json_encode( $scores );
echo '<canvas id="pgm-trendline-chart" height="120"></canvas>';
echo '<canvas id="prv-trendline-chart" height="120"></canvas>';
echo '<script>document.addEventListener("DOMContentLoaded",function(){';
echo 'var ctx=document.getElementById("pgm-trendline-chart").getContext("2d");';
echo 'var ctx=document.getElementById("prv-trendline-chart").getContext("2d");';
echo 'new Chart(ctx,{type:"line",data:{labels:' . $labels_json . ',datasets:[{label:"Visibility Score",data:' . $scores_json . ',borderColor:"#2271b1",tension:0.3,fill:false}]},options:{scales:{y:{min:0,max:1,title:{display:true,text:"Score"}}},plugins:{legend:{display:false}}}});';
echo '});</script>';
echo '</div>';
@@ -119,19 +119,19 @@ class PGM_Ai_Visibility_Panel implements PGM_Dashboard_Panel {
* @return void
*/
private function render_standings( array $standings ): void {
echo '<div class="pgm-card"><h2>' . esc_html__( 'Current Standings', 'peptide-geo-monitor' ) . '</h2>';
echo '<div class="prv-card"><h2>' . esc_html__( 'Current Standings', 'pr-vision' ) . '</h2>';
if ( empty( $standings ) ) {
echo '<p>' . esc_html__( 'No standings data yet.', 'peptide-geo-monitor' ) . '</p></div>';
echo '<p>' . esc_html__( 'No standings data yet.', 'pr-vision' ) . '</p></div>';
return;
}
echo '<table class="wp-list-table widefat fixed striped pgm-standings">';
echo '<table class="wp-list-table widefat fixed striped prv-standings">';
echo '<thead><tr>';
echo '<th>' . esc_html__( 'Peptide', 'peptide-geo-monitor' ) . '</th>';
echo '<th>' . esc_html__( 'Cited?', 'peptide-geo-monitor' ) . '</th>';
echo '<th>' . esc_html__( 'Our Position', 'peptide-geo-monitor' ) . '</th>';
echo '<th>' . esc_html__( 'Top Competing Domains', 'peptide-geo-monitor' ) . '</th>';
echo '<th>' . esc_html__( 'Peptide', 'pr-vision' ) . '</th>';
echo '<th>' . esc_html__( 'Cited?', 'pr-vision' ) . '</th>';
echo '<th>' . esc_html__( 'Our Position', 'pr-vision' ) . '</th>';
echo '<th>' . esc_html__( 'Top Competing Domains', 'pr-vision' ) . '</th>';
echo '</tr></thead><tbody>';
foreach ( $standings as $row ) {

View File

@@ -2,21 +2,21 @@
declare(strict_types=1);
/**
* Seam: contract for all GEO-monitor dashboard panels.
* Seam: contract for all PR Vision dashboard panels.
*
* Each panel renders one data category within the GEO Monitor admin page.
* v1 ships only PGM_Ai_Visibility_Panel. Future panels (keyword rankings,
* schema coverage…) implement this and register with PGM_Collector_Registry.
* Each panel renders one data category within the PR Vision admin page.
* v1 ships only PRV_Ai_Visibility_Panel. Future panels (keyword rankings,
* schema coverage…) implement this and register with PRV_Collector_Registry.
*
* Who triggers: PGM_Admin_Page when building the GEO Monitor page.
* Who triggers: PRV_Admin_Page when building the PR Vision page.
* Dependencies: None — pure interface.
*
* @see class-pgm-ai-visibility-panel.php — v1 implementation.
* @see class-pgm-collector-registry.php — Registration hub.
* @see class-prv-ai-visibility-panel.php — v1 implementation.
* @see class-prv-collector-registry.php — Registration hub.
* @see ARCHITECTURE.md — §Collector/Panel seam.
* @package PeptideGeoMonitor
* @package PrVision
*/
interface PGM_Dashboard_Panel {
interface PRV_Dashboard_Panel {
/**
* Render the panel HTML into the current output buffer.