feat(phase2b): P2b.1 — Research_Fanout + Research_Judge (curate stage) (#178, v0.28.0)
Additive: parallel research fan-out (curl_multi, quorum, cost-reserve-before-dispatch) + curate judge (dedup/score/run_sources). Live Economy path untouched; Authority activates at P2b.4. QA APPROVE-WITH-P2 685c40b; CI green (PHPUnit verified on VPS runner). Agent-Session: prab-phase2b-1-merge
This commit is contained in:
82
includes/core/class-research-source-scorer.php
Normal file
82
includes/core/class-research-source-scorer.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* phpcs:ignore WordPress.Files.FileName.InvalidClassFileName -- class naming convention differs from WordPress standard
|
||||
*
|
||||
* Source authority scorer for the Authority pipeline curate stage.
|
||||
*
|
||||
* What: Computes a quality_score for each research source by multiplying
|
||||
* its agent-assigned relevance by a source-type authority weight
|
||||
* derived from the URL scheme and hostname. Weight tiers:
|
||||
* peer-reviewed (DOI/PubMed/NCBI → 1.0), institutional (.gov /
|
||||
* .edu / WHO / FDA → 0.85), preprint (medRxiv/bioRxiv → 0.70),
|
||||
* general HTTPS (→ 0.60), HTTP or missing (→ 0.40).
|
||||
* Who triggers it: PRAutoBlogger_Research_Judge (curate stage) only.
|
||||
* Not wired into the Economy path.
|
||||
* Dependencies: none — pure computation.
|
||||
*
|
||||
* @see core/class-research-judge.php — Sole consumer.
|
||||
* @see ARCHITECTURE.md — Phase 2b curate stage.
|
||||
*/
|
||||
class PRAutoBlogger_Research_Source_Scorer {
|
||||
|
||||
/**
|
||||
* Add a quality_score field to a source array in place.
|
||||
*
|
||||
* @param array{url: string, title: string, excerpt: string, relevance: float, agent_role: string} $source Source from a research agent.
|
||||
* @return array{url: string, title: string, excerpt: string, relevance: float, agent_role: string, quality_score: float} Source with quality_score added.
|
||||
*
|
||||
* Side effects: none.
|
||||
*/
|
||||
public function score( array $source ): array {
|
||||
$source['quality_score'] = round(
|
||||
$source['relevance'] * $this->weight( $source['url'] ?? '' ),
|
||||
4
|
||||
);
|
||||
return $source;
|
||||
}
|
||||
|
||||
// ── Private helpers ─────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Authority weight for a source URL.
|
||||
*
|
||||
* @param string $url Source URL.
|
||||
* @return float Weight in [0.40, 1.0].
|
||||
*/
|
||||
private function weight( string $url ): float {
|
||||
$u = strtolower( $url );
|
||||
|
||||
if (
|
||||
false !== strpos( $u, 'doi.org' ) ||
|
||||
false !== strpos( $u, 'pubmed.ncbi' ) ||
|
||||
false !== strpos( $u, 'ncbi.nlm.nih' )
|
||||
) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (
|
||||
false !== strpos( $u, '.gov' ) ||
|
||||
false !== strpos( $u, '.edu' ) ||
|
||||
false !== strpos( $u, 'who.int' ) ||
|
||||
false !== strpos( $u, 'fda.gov' )
|
||||
) {
|
||||
return 0.85;
|
||||
}
|
||||
|
||||
if (
|
||||
false !== strpos( $u, 'medrxiv' ) ||
|
||||
false !== strpos( $u, 'biorxiv' ) ||
|
||||
false !== strpos( $u, 'preprint' )
|
||||
) {
|
||||
return 0.70;
|
||||
}
|
||||
|
||||
if ( 0 === strpos( $u, 'https://' ) ) {
|
||||
return 0.60;
|
||||
}
|
||||
|
||||
return 0.40;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user