feat(phase2b): P2b.4 — tier routing + Authority pipeline + citation/imagery gates (#181, v0.31.0)
Authority_Pipeline orchestrator (research→curate→draft→editorial→seo→publish gate) + per-category tier router behind master flag prautoblogger_authority_pipeline_enabled (DEFAULT OFF — zero behavior change until enabled). Cost-ceiling halts→hold; citation + imagery gates. QA APPROVE b086079; CI green (phpcs+phpunit VPS-verified). Agent-Session: prab-phase2b-4-merge
This commit is contained in:
100
includes/core/class-tier-router.php
Normal file
100
includes/core/class-tier-router.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* phpcs:ignore WordPress.Files.FileName.InvalidClassFileName -- class naming convention differs from WordPress standard
|
||||
*
|
||||
* Per-category generation tier router for the Authority pipeline.
|
||||
*
|
||||
* What: Resolves whether a given article idea should enter the Authority
|
||||
* pipeline or fall through to the Economy single-pass. The master
|
||||
* switch (`prautoblogger_authority_pipeline_enabled`) defaults FALSE,
|
||||
* which guarantees byte-identical behaviour to today — no articles
|
||||
* ever touch the Authority path unless an operator explicitly enables
|
||||
* the flag. When the flag is ON, per-category overrides in
|
||||
* `prautoblogger_category_tiers` demote specific categories to
|
||||
* Economy; every other category (unclassified, new, missing) stays
|
||||
* at the Authority default.
|
||||
*
|
||||
* Who triggers it: PRAutoBlogger_Article_Worker::generate() (P2b.4).
|
||||
* Dependencies: WordPress get_option(), PRAutoBlogger_Article_Idea.
|
||||
*
|
||||
* @see providers/interface-tier-router.php — Interface this class implements.
|
||||
* @see core/class-article-worker.php — Call site (3-line tier check).
|
||||
* @see core/class-authority-pipeline.php — Authority path executed on 'authority'.
|
||||
* @see ARCHITECTURE.md — Phase 2b tier routing.
|
||||
*/
|
||||
class PRAutoBlogger_Tier_Router implements PRAutoBlogger_Tier_Router_Interface {
|
||||
|
||||
/** Option key for the master Authority pipeline feature flag. */
|
||||
public const OPTION_MASTER_FLAG = 'prautoblogger_authority_pipeline_enabled';
|
||||
|
||||
/** Option key for the per-category tier map (serialized array). */
|
||||
public const OPTION_CATEGORY_TIERS = 'prautoblogger_category_tiers';
|
||||
|
||||
/** Default tier when a category has no explicit override: Authority. */
|
||||
private const DEFAULT_TIER = 'authority';
|
||||
|
||||
/**
|
||||
* Resolve the generation tier for an article idea.
|
||||
*
|
||||
* Returns 'economy' immediately when the master flag is OFF — this is
|
||||
* the production default and must guarantee zero behaviour change
|
||||
* relative to the pre-P2b.4 codebase.
|
||||
*
|
||||
* When the master flag is ON, looks up the idea's article_type in the
|
||||
* per-category tier map. Values of 'economy' explicitly demote that
|
||||
* category. Any other value, or no entry at all, keeps the Authority
|
||||
* default.
|
||||
*
|
||||
* Side effects: two get_option() calls (cached by WordPress object cache).
|
||||
*
|
||||
* @param PRAutoBlogger_Article_Idea $idea The article idea to route.
|
||||
* @return string 'authority' or 'economy'
|
||||
*/
|
||||
public function resolve( PRAutoBlogger_Article_Idea $idea ): string {
|
||||
if ( ! $this->is_master_flag_on() ) {
|
||||
return 'economy';
|
||||
}
|
||||
|
||||
return $this->resolve_from_category( $idea->get_article_type() );
|
||||
}
|
||||
|
||||
// ── Private helpers ──────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Whether the Authority pipeline master switch is enabled.
|
||||
*
|
||||
* The option defaults to false (disabled). Operators must explicitly
|
||||
* set it to '1' or true via wp_options / WP admin to enable the path.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_master_flag_on(): bool {
|
||||
$flag = get_option( self::OPTION_MASTER_FLAG, false );
|
||||
return in_array( $flag, array( '1', true, 1 ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve tier from the per-category tier map.
|
||||
*
|
||||
* The map is a serialized PHP array (stored via WordPress options) of
|
||||
* `['category_slug' => 'economy']`. Only 'economy' is a meaningful
|
||||
* explicit value — anything else (including 'authority') is treated
|
||||
* as "keep the default".
|
||||
*
|
||||
* Unrecognised or empty maps → default Authority tier (additive safety).
|
||||
*
|
||||
* @param string $article_type Article type / category slug from the idea.
|
||||
* @return string 'authority' or 'economy'
|
||||
*/
|
||||
private function resolve_from_category( string $article_type ): string {
|
||||
$raw = get_option( self::OPTION_CATEGORY_TIERS, array() );
|
||||
$map = is_array( $raw ) ? $raw : array();
|
||||
|
||||
$tier = $map[ $article_type ] ?? self::DEFAULT_TIER;
|
||||
|
||||
// Only 'economy' is a valid explicit demote; any other value defaults.
|
||||
return 'economy' === $tier ? 'economy' : 'authority';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user