Spaces:
Sleeping
Sleeping
| defined( 'ABSPATH' ) || exit; | |
| /** | |
| * Actor Handoff Log β two-axis attribution (Board #23). | |
| * | |
| * Provides a clear, auditable boundary between AI-operated actor mode | |
| * and human-operated actor mode WITHOUT mutating Fluent's own comment | |
| * tables. Strictly additive: a small dedicated table records who | |
| * "pressed send" for a given actor-authored comment. | |
| * | |
| * The two axes: | |
| * created_by β the actor (Bridget, etc.). The displayed author. Unchanged. | |
| * committed_by β the user who pressed send (a human user, or an agent | |
| * service account user). Recorded here, queried via | |
| * SA_Orch_Actor_Handoff::get_committer(). | |
| * | |
| * Operator-mode detection β the full provenance chain works once Board #16 | |
| * (Token + Usage Visibility) ships its LLM token log. Until then, the | |
| * token-presence check returns 'unknown' and detect_mode reflects that | |
| * honestly: | |
| * | |
| * committer recorded + token row found β 'ai' | |
| * committer recorded + token row NOT found β 'human' | |
| * committer recorded + token state unknown β 'unknown' (pre-#16; honest) | |
| * committer NOT recorded β 'unknown' | |
| * | |
| * The token-presence check is implemented as a filter: | |
| * | |
| * apply_filters( 'sa_orch_handoff_has_llm_token', null, $kind, $comment_id ); | |
| * | |
| * Board #16 will register a callback that consults the token log. The | |
| * default return of null means "unknown" β never a false positive. | |
| * | |
| * Doctrine constraints honored: | |
| * - Actors remain non-binding; this layer is observational, not enforcing | |
| * - No impact to Board progression rules | |
| * - No schema refactors β strictly additive (one new table) | |
| * - No Asterion writes | |
| * - No automation | |
| * - No UI surface beyond what already exists | |
| */ | |
| class SA_Orch_Actor_Handoff { | |
| const KIND_FLUENT_BOARDS = 'fluent_boards'; | |
| const KIND_FLUENT_SUPPORT = 'fluent_support'; | |
| const MODE_AI = 'ai'; | |
| const MODE_HUMAN = 'human'; | |
| const MODE_UNKNOWN = 'unknown'; | |
| private static function table(): string { | |
| global $wpdb; | |
| return $wpdb->prefix . SA_ORCH_DB_PREFIX . 'actor_handoff'; | |
| } | |
| /** | |
| * Record (or update) the committer for an actor-authored comment. | |
| * Idempotent on (kind, comment_id) β re-recording replaces the prior row. | |
| * | |
| * Returns true on success, false on invalid input or DB failure. | |
| */ | |
| public static function record_committer( string $kind, int $comment_id, int $committed_by_user_id ): bool { | |
| if ( $comment_id <= 0 || $committed_by_user_id <= 0 ) { | |
| return false; | |
| } | |
| $kind = sanitize_key( $kind ); | |
| if ( $kind === '' ) return false; | |
| global $wpdb; | |
| $tbl = self::table(); | |
| // Replace prior row, if any. Keeps the table thin. | |
| $wpdb->delete( $tbl, [ | |
| 'comment_kind' => $kind, | |
| 'comment_id' => $comment_id, | |
| ] ); | |
| $ok = $wpdb->insert( $tbl, [ | |
| 'comment_kind' => $kind, | |
| 'comment_id' => $comment_id, | |
| 'committed_by_user_id' => $committed_by_user_id, | |
| 'recorded_at' => current_time( 'mysql', true ), | |
| ] ); | |
| return $ok !== false; | |
| } | |
| /** | |
| * Get the recorded committer for a comment, or null if none recorded. | |
| */ | |
| public static function get_committer( string $kind, int $comment_id ): ?int { | |
| if ( $comment_id <= 0 ) return null; | |
| $kind = sanitize_key( $kind ); | |
| if ( $kind === '' ) return null; | |
| global $wpdb; | |
| $row = $wpdb->get_var( $wpdb->prepare( | |
| "SELECT committed_by_user_id FROM " . self::table() . " | |
| WHERE comment_kind = %s AND comment_id = %d | |
| ORDER BY id DESC LIMIT 1", | |
| $kind, | |
| $comment_id | |
| ) ); | |
| return $row !== null ? (int) $row : null; | |
| } | |
| /** | |
| * Detect operator mode for a comment. Returns one of the MODE_* constants. | |
| * Never lies about uncertainty β returns 'unknown' rather than guessing. | |
| */ | |
| public static function detect_mode( string $kind, int $comment_id ): string { | |
| $committer = self::get_committer( $kind, $comment_id ); | |
| if ( $committer === null ) { | |
| return self::MODE_UNKNOWN; | |
| } | |
| /** | |
| * Filter that signals whether an LLM token row exists for this commit. | |
| * Returns: true (token row found β AI mode), | |
| * false (no token row β human mode), | |
| * null (unknown β token log not yet integrated, default). | |
| * | |
| * Board #16 will register a callback that consults the token log. | |
| */ | |
| $token_present = apply_filters( | |
| 'sa_orch_handoff_has_llm_token', | |
| null, | |
| $kind, | |
| $comment_id | |
| ); | |
| if ( $token_present === null ) return self::MODE_UNKNOWN; | |
| if ( $token_present === true ) return self::MODE_AI; | |
| return self::MODE_HUMAN; | |
| } | |
| } | |