RcmEmailAutomation / sa-orchestration /includes /class-sa-strategy.php
NujacsaintS's picture
reseed
f51c224
Raw
History Blame Contribute Delete
3.32 kB
<?php
defined( 'ABSPATH' ) || exit;
/**
* Strategy LLM Review orchestrator.
*
* Layer 3 of the review stack. Delegates to the active provider (resolved
* via SA_Orch_LLM_Providers::get_active_provider()) and adds metadata
* about which provider produced the result.
*
* Constraints (enforced by contract, not code):
* - The Strategy Review NEVER overrides closure_state or
* needs_human_arbitration. Those are governed by the deterministic
* audit and ultimately by human arbitration.
* - Strategy Review is purely advisory.
*/
class SA_Orch_Strategy {
/**
* Run a Strategy Review against the trace + deterministic audit.
*
* Returns the provider's review_trace() output augmented with:
* - provider_id (string)
* - provider_name (string)
* - provider_error (string, optional — present if the provider threw)
*/
public static function review( array $trace, array $deterministic_audit ): array {
$configured = SA_Orch_LLM_Providers::get_active_provider();
$configured_id = $configured->id();
$configured_name = $configured->name();
$fallback_used = false;
$error_message = null;
$used = $configured;
try {
$review = $configured->review_trace( $trace, $deterministic_audit );
} catch ( \Throwable $e ) {
// Fallback to simulated on any error from the configured provider
$fallback = new SA_Orch_LLM_Provider_Simulated();
$review = $fallback->review_trace( $trace, $deterministic_audit );
$error_message = $e->getMessage();
$fallback_used = true;
$used = $fallback;
}
// Defensive: enforce required keys
$review = wp_parse_args( $review, [
'summary' => '',
'agreement_with_audit' => 'partial',
'additional_risks' => [],
'suggested_next_action' => '',
'confidence' => 'low',
] );
// Conservative confidence floor (v0.5.2): when the deterministic audit
// cannot evaluate closure (closure_confidence='n/a' — i.e. no acceptance
// events recorded), the strategy layer MUST collapse to 'low'. Prevents
// LLM-shaped over-confidence on Demands with no acceptance evidence.
// Cross-cutting: applied here so any provider (including future ones)
// gets it for free, regardless of what the model returned.
if ( ( $deterministic_audit['closure_confidence'] ?? '' ) === 'n/a'
&& in_array( $review['confidence'], [ 'medium', 'high' ], true ) ) {
$review['confidence'] = 'low';
}
// Provider used to actually produce this output
$review['provider_id'] = $used->id();
$review['provider_name'] = $used->name();
// Configured provider (what the operator selected)
$review['configured_provider_id'] = $configured_id;
$review['configured_provider_name'] = $configured_name;
// Fallback transparency
$review['fallback_used'] = $fallback_used;
if ( $error_message !== null ) {
$review['provider_error'] = $error_message;
}
return $review;
}
}