v0.3.2 — adopt estate CI: PHPUnit suite + reusable pipeline + governance workflows

- Convert 17 hand-rolled tests to PHPUnit TestCases (tests: stubs pattern)
  P0 security tests preserved: key-leak/encryption (KeyStoreTest),
  capture-allowlist/executor-path sentinel (CaptureWriterTest)
- Add phpunit.xml.dist + update tests/bootstrap.php (Composer autoloader first)
- Add phpunit/phpunit ^9.6 + yoast/phpunit-polyfills ^2.0 to require-dev
- composer test -> vendor/bin/phpunit --configuration phpunit.xml.dist
- ci.yml: thin caller of peptide-e2e reusable CI (tests: stubs, has_js: true,
  workflow_call trigger, permissions: contents: write)
- deploy.yml: estate pattern caller of peptide-e2e deploy-app.yml@main
  (target_path: wp-content/plugins/pr-vision, gated on reusable CI)
  Pull-deploy on Hostinger stays as break-glass
- Add cto-review.yml (Haiku-only, A/B panel dropped 2026-06-12)
- Add main-push-audit.yml (direct-push tripwire)

Agent-Session: claude-adopt-ci-20260616
This commit is contained in:
peptiderepo
2026-06-16 15:25:22 +00:00
parent 1d8f024380
commit 01a9356c16
26 changed files with 2459 additions and 182 deletions

View File

@@ -0,0 +1,82 @@
<?php
/**
* Tests for uninstall purge: all prv_ options deleted, lock cleared.
*
* @package PrVision
*/
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
/**
* @covers PRV_Activator
* @covers PRV_Deactivator
*/
class UninstallTest extends TestCase {
protected function setUp(): void {
prv_test_reset();
if ( ! defined( 'PRV_OPENROUTER_API_KEY' ) ) {
define( 'PRV_OPENROUTER_API_KEY', 'sk-or-test-key' );
}
if ( ! defined( 'PRV_CF_ACCOUNT_ID' ) ) {
define( 'PRV_CF_ACCOUNT_ID', '' );
}
if ( ! defined( 'PRV_CF_GATEWAY_ID' ) ) {
define( 'PRV_CF_GATEWAY_ID', '' );
}
}
public function test_uninstall_purges_all_prv_options(): void {
// Populate all known prv_ options.
PRV_Model_Registry::run_migration_v2();
PRV_Config_Version::maybe_seed_initial_version();
update_option( 'prv_monthly_budget_usd', 5.0 );
update_option( 'prv_peptides', [] );
update_option( 'prv_prompt_intents', [] );
update_option( PRV_Config::CADENCE_KEY, 'weekly' );
update_option( 'prv_api_key_status', 'ok' );
update_option( 'prv_api_key_last_check', '2026-06-14 12:00:00' );
update_option( 'prv_last_run_at', '2026-06-14 12:00:00' );
update_option( 'prv_last_run_counts', [] );
update_option( 'prv_last_run_truncated', 0 );
update_option( 'prv_last_run_truncated_at', '' );
update_option( 'prv_provider_key_enc', 'dummy-encrypted-ciphertext-value' );
update_option( 'prv_schema_version', PRV_SCHEMA_VERSION );
$GLOBALS['prv_test_state']['transients'][ PRV_Run_Lock::LOCK_KEY ] = time();
$GLOBALS['prv_test_state']['cron_events'][ PRV_CRON_HOOK ] = [ 'timestamp' => time() + 3600, 'schedule' => 'weekly' ];
// Verify pre-uninstall state.
$this->assertNotFalse( get_option( 'prv_models' ) );
$this->assertNotFalse( get_option( 'prv_monthly_budget_usd' ) );
$this->assertNotFalse( get_option( 'prv_api_key_status' ) );
$this->assertNotFalse( get_option( 'prv_active_config_version' ) );
$this->assertNotFalse( get_transient( PRV_Run_Lock::LOCK_KEY ) );
$this->assertTrue( PRV_Cron::is_scheduled() );
// Simulate uninstall: delete all prv_ options.
$keys_to_purge = array_filter(
array_keys( $GLOBALS['prv_test_state']['options'] ),
static fn( $k ) => str_starts_with( $k, 'prv_' )
);
foreach ( $keys_to_purge as $k ) {
unset( $GLOBALS['prv_test_state']['options'][ $k ] );
}
delete_transient( PRV_Run_Lock::LOCK_KEY );
wp_clear_scheduled_hook( PRV_CRON_HOOK );
// Verify all prv_ options are gone.
$this->assertFalse( get_option( 'prv_models' ) );
$this->assertFalse( get_option( 'prv_monthly_budget_usd' ) );
$this->assertFalse( get_option( 'prv_api_key_status' ) );
$this->assertFalse( get_option( 'prv_active_config_version' ) );
$this->assertFalse( get_option( 'prv_config_versions' ) );
$this->assertFalse( get_option( 'prv_models_schema_version' ) );
$this->assertFalse( get_option( 'prv_schema_version' ) );
$this->assertFalse( get_option( 'prv_provider_key_enc' ) );
$this->assertFalse( get_option( 'prv_last_run_truncated' ) );
$this->assertFalse( get_transient( PRV_Run_Lock::LOCK_KEY ) );
$this->assertFalse( PRV_Cron::is_scheduled() );
}
}